T-SQL Dynamic SQL and Temp Tables

前端 未结 5 1821
梦毁少年i
梦毁少年i 2020-11-28 11:04

It looks like #temptables created using dynamic SQL via the EXECUTE string method have a different scope and can\'t be referenced by \"fixed\" SQLs in the same stored proced

相关标签:
5条回答
  • 2020-11-28 11:42

    I would strongly suggest you have a read through http://www.sommarskog.se/arrays-in-sql-2005.html

    Personally I like the approach of passing a comma delimited text list, then parsing it with text to table function and joining to it. The temp table approach can work if you create it first in the connection. But it feel a bit messier.

    0 讨论(0)
  • 2020-11-28 11:47

    You first need to create your table first then it will be available in the dynamic SQL.

    This works:

    CREATE TABLE #temp3 (id INT)
    EXEC ('insert #temp3 values(1)')
    
    SELECT *
    FROM #temp3
    

    This will not work:

    EXEC (
            'create table #temp2 (id int)
             insert #temp2 values(1)'
            )
    
    SELECT *
    FROM #temp2
    

    In other words:

    1. Create temp table
    2. Execute proc
    3. Select from temp table

    Here is complete example:

    CREATE PROC prTest2 @var VARCHAR(100)
    AS
    EXEC (@var)
    GO
    
    CREATE TABLE #temp (id INT)
    
    EXEC prTest2 'insert #temp values(1)'
    
    SELECT *
    FROM #temp
    
    0 讨论(0)
  • 2020-11-28 11:49

    I had the same issue that @Muflix mentioned. When you don't know the columns being returned, or they are being generated dynamically, what I've done is create a global table with a unique id, then delete it when I'm done with it, this looks something like what's shown below:

    DECLARE @DynamicSQL NVARCHAR(MAX)
    DECLARE @DynamicTable VARCHAR(255) = 'DynamicTempTable_' + CONVERT(VARCHAR(36), NEWID())
    DECLARE @DynamicColumns NVARCHAR(MAX)
    
    --Get "@DynamicColumns", example: SET @DynamicColumns = '[Column1], [Column2]'
    
    SET @DynamicSQL = 'SELECT ' + @DynamicColumns + ' INTO [##' + @DynamicTable + ']' + 
         ' FROM [dbo].[TableXYZ]'
    
    EXEC sp_executesql @DynamicSQL
    
    SET @DynamicSQL = 'IF OBJECT_ID(''tempdb..##' + @DynamicTable + ''' , ''U'') IS NOT NULL ' + 
        ' BEGIN DROP TABLE [##' + @DynamicTable + '] END'
    
    EXEC sp_executesql @DynamicSQL
    

    Certainly not the best solution, but this seems to work for me.

    0 讨论(0)
  • 2020-11-28 11:58

    Result sets from dynamic SQL are returned to the client. I have done this quite a lot.

    You're right about issues with sharing data through temp tables and variables and things like that between the SQL and the dynamic SQL it generates.

    I think in trying to get your temp table working, you have probably got some things confused, because you can definitely get data from a SP which executes dynamic SQL:

    USE SandBox
    GO
    
    CREATE PROCEDURE usp_DynTest(@table_type AS VARCHAR(255))
    AS 
    BEGIN
        DECLARE @sql AS VARCHAR(MAX) = 'SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''' + @table_type + ''''
        EXEC (@sql)
    END
    GO
    
    EXEC usp_DynTest 'BASE TABLE'
    GO
    
    EXEC usp_DynTest 'VIEW'
    GO
    
    DROP PROCEDURE usp_DynTest
    GO
    

    Also:

    USE SandBox
    GO
    
    CREATE PROCEDURE usp_DynTest(@table_type AS VARCHAR(255))
    AS 
    BEGIN
        DECLARE @sql AS VARCHAR(MAX) = 'SELECT * INTO #temp FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''' + @table_type + '''; SELECT * FROM #temp;'
        EXEC (@sql)
    END
    GO
    
    EXEC usp_DynTest 'BASE TABLE'
    GO
    
    EXEC usp_DynTest 'VIEW'
    GO
    
    DROP PROCEDURE usp_DynTest
    GO
    
    0 讨论(0)
  • 2020-11-28 12:06

    1st Method - Enclose multiple statements in the same Dynamic SQL Call:

    DECLARE @DynamicQuery NVARCHAR(MAX)
    
    SET @DynamicQuery = 'Select * into #temp from (select * from tablename) alias 
    select * from #temp
    drop table #temp'
    
    EXEC sp_executesql @DynamicQuery
    

    2nd Method - Use Global Temp Table:
    (Careful, you need to take extra care of global variable.)

    IF OBJECT_ID('tempdb..##temp2') IS NULL
    BEGIN
        EXEC (
                'create table ##temp2 (id int)
                 insert ##temp2 values(1)'
                )
    
        SELECT *
        FROM ##temp2
    END
    

    Don't forget to delete ##temp2 object manually once your done with it:

    IF (OBJECT_ID('tempdb..##temp2') IS NOT NULL)
    BEGIN
         DROP Table ##temp2
    END
    

    Note: Don't use this method 2 if you don't know the full structure on database.

    0 讨论(0)
提交回复
热议问题