50

代码如下:

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。但我不知道怎么做。

谁能帮我解决这个问题?

4

9 回答 9

45

尝试:

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

这闻起来真的很糟糕,就像一个 sql 注入漏洞。


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

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

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

于 2009-03-19T12:56:56.117 回答
36

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

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

希望这会有所帮助,杰西

于 2009-06-16T18:50:33.577 回答
22

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

于 2010-11-15T16:03:48.887 回答
11

动态创建名称中带有 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 
于 2013-03-15T17:26:54.270 回答
8
INSERT INTO #TempTable
EXEC(@SelectStatement)
于 2011-06-14T22:29:39.563 回答
0
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
于 2012-03-31T11:01:03.480 回答
0
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
于 2016-11-22T08:29:58.677 回答
0

尝试下面的代码,使用 T-SQL 从存储过程输出动态创建临时表

declare @ExecutionName varchar(1000) = 'exec [spname] param1,param2 '
declare @sqlStr varchar(max) = ''

   declare @tempTableDef nvarchar(max) =   
  (  
  SELECT distinct   
   STUFF(  
    (  
     SELECT ','+a.[name]+' '+[system_type_name]  
  +'  
   ' AS [text()]  
     FROM sys.dm_exec_describe_first_result_set  (@ExecutionName, null, 0) a  
     ORDER BY a.column_ordinal  
     FOR XML PATH ('')  
    ), 1, 1, '') tempTableDef   

  FROM sys.dm_exec_describe_first_result_set  (@ExecutionName, null, 0) b  
  )  

  IF ISNULL(@tempTableDef ,'') = '' RAISERROR( 'Invalid SP Configuration. At least one column is required in Select list of SP output.',16,1) ;    
                                      
  set @tempTableDef='CREATE TABLE #ResultDef   
  (  
  ' + REPLACE(@tempTableDef,'
','') +'  
  )  

  INSERT INTO #ResultDef   
  ' + @ExecutionName    
          
  Select  @sqlStr  = @tempTableDef +' Select * from  #ResultDef '   
exec(@sqlStr)
于 2021-03-18T11:03:29.677 回答
-1

不确定我是否理解得很好,但也许您可以在字符串中形成 CREATE 语句,然后执行该字符串?这样您就可以根据需要添加任意数量的列。

于 2009-03-19T12:40:16.080 回答