Результаты динамического SQL во временную таблицу в хранимой процедуре SQL

StackOverflow https://stackoverflow.com/questions/662049

  •  20-08-2019
  •  | 
  •  

Вопрос

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

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 в общем виде.Но я не знаю как.

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

Это было полезно?

Решение

Пытаться:

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

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


исправление (согласно комментарию @CarpeDiem):

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

также опустите 'execute' если строка sql не является процедурой

Другие советы

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

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 создается на «более низком уровне», чем блок выполнения кода.Чтобы исправить это, используйте глобальную временную таблицу:

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

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

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

динамически создайте глобальную временную таблицу с GUID в имени.Затем вы можете работать с ним в своем коде через dyn sql, не беспокоясь о том, что его будет использовать другой процесс, вызывающий тот же процесс.Это полезно, когда вы не знаете, чего ожидать от базовой выбранной таблицы при каждом ее запуске, поэтому вы не можете заранее явно создать временную таблицу.т.е. вам нужно использовать синтаксис 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 
INSERT INTO #TempTable
EXEC(@SelectStatement)
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
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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top