动态SQL在SQL存储过程中生成临时表

Dha*_*ana 44 t-sql sql-server dynamic-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
Run Code Online (Sandbox Code Playgroud)

问题是我想调用可以返回不同列的不同过程.因此,我必须一般地定义表#T1.但我不知道怎么做.

任何人都可以帮我解决这个问题吗?

Joe*_*orn 37

尝试:

SELECT into #T1 execute ('execute ' + @SQLString )
Run Code Online (Sandbox Code Playgroud)

这就像sql注入漏洞一样真的很糟糕.


更正(根据@ CarpeDiem的评论):

INSERT into #T1 execute ('execute ' + @SQLString )
Run Code Online (Sandbox Code Playgroud)

另外,'execute'如果sql字符串不是过程,则省略

  • 我认为答案是*INSERT*进#T1执行('执行'+ @SQLString)... (3认同)
  • 我有同样的问题,如果我不知道号码怎么办?@SQLString 返回的列数?那该怎么办。 (2认同)
  • #T1 必须在上述答案生效之前创建。 (2认同)

小智 31

您可以动态地定义表,就像动态插入表一样,但问题在于临时表的范围.例如,这段代码:

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
Run Code Online (Sandbox Code Playgroud)

将返回错误"无效的对象名称'#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
Run Code Online (Sandbox Code Playgroud)

希望这有帮助,杰西

  • 就是这个!现在我可以在我的存储过程中创建表,名称通过参数传递!如果我能给10票! (2认同)
  • 多亏了你,我终于接触到了SQL的“精神世界”,并召唤了在那里创建的恶魔动态表从其中回来了!:) (2认同)

Run*_*pot 16

注意全局临时表解决方案,因为如果两个用户同时使用相同的例程,这可能会失败,因为所有用户都可以看到全局临时表...


小智 10

创建名称中动态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 
Run Code Online (Sandbox Code Playgroud)


MTS*_*MTS 7

INSERT INTO #TempTable
EXEC(@SelectStatement)
Run Code Online (Sandbox Code Playgroud)