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

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

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

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

Ответы [ 8 ]

37 голосов
/ 19 марта 2009

Попробуйте:

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

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


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

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

также опустите 'execute', если строка sql отличается от процедуры

31 голосов
/ 16 июня 2009

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

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

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

16 голосов
/ 15 ноября 2010

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

10 голосов
/ 15 марта 2013

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...