使用动态SQL创建表

时间:2013-02-19 14:18:44

标签: sql sql-server sql-server-2008-r2 dynamic-sql

以下作品:

DECLARE @cols AS NVARCHAR(MAX),
        @query AS NVARCHAR(MAX);

SET @cols = 
STUFF
    (
        (
        SELECT   ',' + QUOTENAME(b."NewName")
        FROM    (
                    SELECT  myKey, 
                        win = SUM(win)
                    FROM    xxx.dbo.yyy
                    GROUP BY myKey
                    ) x
                    INNER JOIN #NameSwitch b ON
                        x.myKey = b.myKey
        ORDER BY x.win DESC
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'');


SET @query =    
    'SELECT [Measure],' + @cols + ' 
    FROM  
        (
            SELECT  [NewName], [Measure], [Amount]
            FROM    #UnpivottedData x
        ) x
        PIVOT 
        (
            SUM(Amount)
            FOR [NewName] in (' + @cols + ')
        ) p ';

EXECUTE(@query);

但问题是我想将结果输入临时表#xxx,然后才能通过SELECT * FROM #xxx使用此数据。

在运行上述内容之前,是否需要CREATE #xxx使用dynamic sql?如果是这样的话,任何人都可以指向我这样做的例子。

3 个答案:

答案 0 :(得分:2)

尝试改变包括进入条款

SET @query =    
'SELECT [Measure],' + @cols + ' 
 into ##xxx
FROM  
    (
        SELECT  [NewName], [Measure], [Amount]
        FROM    #UnpivottedData x
    ) x
    PIVOT 
    (
        SUM(Amount)
        FOR [NewName] in (' + @cols + ')
    ) p ';

这将为结果创建临时表...

如果您真的想在选择之前创建..

您需要收集列的类型以构建create table statment ..

答案 1 :(得分:2)

弗雷德里克几乎正确 -

动态SQL在与调用批处理不同的范围内执行。在动态SQL批处理中声明的任何临时对象(表,变量)仅在动态SQL批处理中可用。您将能够SELECT INTO 全局临时表 - 因为这些是特定于连接的,并且将在动态SQL批处理中保留。

sp_executesql

答案 2 :(得分:1)

似乎你能够获得列名,所以我假设你可以获得列类型。 所以你可以这样做(pesudo代码)

CREATE TABLE #XXX (Measure <type>)
//
   generate scripts like 
SET @SQL = N'ALTER TABLE #XXX ADD '+ ColumnName+' '+ColumnTypeInfo
EXEC SP_ExecuteSQL @SQL
//

SET @query =    
    'INSERT INTO #XXX ([MEASURE], '+@cols+')
     SELECT [Measure],' + @cols + ' 
    FROM  
        (
            SELECT  [NewName], [Measure], [Amount]
            FROM    #UnpivottedData x
        ) x
        PIVOT 
        (
            SUM(Amount)
            FOR [NewName] in (' + @cols + ')
        ) p ';

EXECUTE(@query);

P.S。

  1. 我,我自己会选择EXEC sp_executeSQL @SQL而不是EXEC (@SQL),但在这种情况下只是一个品味问题
  2. 我会简化代码 - 你真的不需要STUFF部分,因为你需要在连接中使用第一个逗号,所以不需要删除它。此外,您只是强制XML列(带有TYPE子句)将其转换为NVARCHAR
  3. 稍后修改

    免责声明:未经测试,因为我没有您的表结构和数据

    DECLARE @cols NVARCHAR(MAX),
            @query NVARCHAR(MAX), 
            @alter_query NVARCHAR(max);
    
    SET @cols = 
            (
            SELECT   ',' + QUOTENAME(b."NewName")
            FROM    (
                        SELECT  myKey, 
                            win = SUM(win)
                        FROM    xxx.dbo.yyy
                        GROUP BY myKey
                        ) x
                        INNER JOIN #NameSwitch b ON
                            x.myKey = b.myKey
            ORDER BY x.win DESC
            FOR XML PATH('')
            ) -- this will render smth like ",col1,col2" 
    SET @alter_query = 
            (
            SELECT   ';ALTER TABLE #XXX ADD ' + QUOTENAME(b."NewName") +' '+ QUOTENAME(b."ColType") +' NULL'
            FROM    (
                        SELECT  myKey, 
                            win = SUM(win)
                        FROM    xxx.dbo.yyy
                        GROUP BY myKey
                        ) x
                        INNER JOIN #NameSwitch b ON
                            x.myKey = b.myKey
            ORDER BY x.win DESC
            FOR XML PATH('')
            ) -- this will render smth like ";ALTER TABLE #XXX ADD col1 VARCHAR(MAX);ALTER ..." 
    
    CREATE TABLE #XXX (Measure INT NULL)
    
    EXEC sp_ExecuteSQL @alter_query
    
    SET @query =    
        'INSERT INTO #XXX (Measure+'@Cols+') SELECT [Measure]' + @cols + ' 
        FROM  
            (
                SELECT  [NewName], [Measure], [Amount]
                FROM    #UnpivottedData x
            ) x
            PIVOT 
            (
                SUM(Amount)
                FOR [NewName] in (' + STUFF(@cols, 1, 1, '') + ') -- here you need the STUFF to remove the first comma
            ) p ';
    
    
    EXEC sp_ExecuteSQL @Query
    
    SELECT * from #XXX