Динамические результаты SQL в таблице temp в SQL Сохраненная процедура

Код выглядит следующим образом:

ALTER PROCEDURE dbo.pdpd_DynamicCall 
@SQLString varchar(4096) = null

AS

Begin

    create TABLE #T1 ( column_1 varchar(10) , column_2 varchar(100) )

    insert into #T1 
        execute ('execute ' + @SQLString )

    select * from #T1 

End

Проблема в том, что я хочу вызывать разные процедуры, которые могут возвращать разные столбцы. Поэтому мне пришлось бы определять таблицу # T1 в общем случае. Но я не знаю, как.

Может ли кто-нибудь помочь мне в решении этой проблемы?

Ответ 1

Try:

SELECT into #T1 execute ('execute ' + @SQLString )

И это сильно пахнет, как уязвимость в sql-инъекции.


коррекция (за комментарий @CarpeDiem):

INSERT into #T1 execute ('execute ' + @SQLString )

также опустить 'execute', если строка sql - это нечто иное, чем процедура

Ответ 2

Динамическую динамическую таблицу можно определить так же, как вы вставляете ее в нее динамически, но проблема связана с объемом временных таблиц. Например, этот код:

DECLARE @sql varchar(max)
SET @sql = 'CREATE TABLE #T1 (Col1 varchar(20))'
EXEC(@sql)
INSERT INTO #T1 (Col1) VALUES ('This will not work.')
SELECT * FROM #T1

вернется с ошибкой "Недопустимое имя объекта" # T1 ". Это связано с тем, что временная таблица # T1 создается на" нижнем уровне", чем блок выполнения кода. Чтобы исправить, используйте глобальную таблицу temp:

DECLARE @sql varchar(max)
SET @sql = 'CREATE TABLE ##T1 (Col1 varchar(20))'
EXEC(@sql)
INSERT INTO ##T1 (Col1) VALUES ('This will work.')
SELECT * FROM ##T1

Надеюсь, это поможет, Джесси

Ответ 3

Будьте осторожны с решением глобальной таблицы temp, поскольку это может завершиться неудачно, если два пользователя используют одну и ту же процедуру одновременно с тем, что глобальная таблица темп видит все пользователи...

Ответ 4

создать глобальную таблицу temp с идентификатором GUID в имени динамически. Затем вы можете работать с ним в своем коде через dyn sql, не опасаясь, что другой процесс, вызывающий тот же sproc, будет использовать его. Это полезно, когда вы не знаете, чего ожидать от базовой выбранной таблицы, каждый раз, когда она запускается, поэтому вы не можете заранее создать таблицу temp заранее. т.е. - вам нужно использовать синтаксис SELECT * INTO

DECLARE @TmpGlobalTable varchar(255) = 'SomeText_' + convert(varchar(36),NEWID())

-- select @TmpGlobalTable 

-- build query
    SET @Sql = 
        'SELECT * INTO [##' + @TmpGlobalTable + '] FROM SomeTable'
EXEC (@Sql)
EXEC ('SELECT * FROM [##' + @TmpGlobalTable + '] ')
EXEC ('DROP TABLE [##' + @TmpGlobalTable + ']')
PRINT 'Dropped Table ' + @TmpGlobalTable 

Ответ 5

INSERT INTO #TempTable
EXEC(@SelectStatement)

Ответ 6

Не уверен, что я хорошо понимаю, но, может быть, вы могли бы сформировать оператор CREATE внутри строки, а затем выполнить эту строку? Таким образом, вы можете добавить столько столбцов, сколько хотите.

Ответ 7

DECLARE @EmpGroup INT =3 ,
        @IsActive BIT=1

DECLARE @tblEmpMaster AS TABLE
        (EmpCode VARCHAR(20),EmpName VARCHAR(50),EmpAddress VARCHAR(500))

INSERT INTO @tblEmpMaster EXECUTE SPGetEmpList @EmpGroup,@IsActive

SELECT * FROM @tblEmpMaster

Ответ 8

CREATE PROCEDURE dbo.pdpd_DynamicCall 
AS
DECLARE @SQLString_2 NVARCHAR(4000)
SET NOCOUNT ON
Begin
    --- Create global temp table
    CREATE TABLE ##T1 ( column_1 varchar(10) , column_2 varchar(100) )

    SELECT @SQLString_2 = 'INSERT INTO ##T1( column_1, column_2) SELECT column_1 = "123", column_2 = "MUHAMMAD IMRON"'
    SELECT @SQLString_2 = REPLACE(@SQLString_2, '"', '''')

    EXEC SP_EXECUTESQL @SQLString_2

    --- Test Display records
    SELECT * FROM ##T1

    --- Drop global temp table 
    IF OBJECT_ID('tempdb..##T1','u') IS NOT NULL
    DROP TABLE ##T1
End