2013-02-19 84 views
1

以下工作:使用動態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才能運行上述操作?如果有的話,任何人都可以指示我完成這個示例的方向。

回答

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], '[email protected]+') 
    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 @SQLEXEC (@SQL),但在這種情況下,僅僅是一個味道
  2. 事我會簡化代碼 - 你並不真正需要的STUFF一部分,因爲你需要你的第一個逗號在你的連接中,所以沒有必要刪除它。此外,您也迫使一個XML列(與TYPE條款)僅將其轉換爲NVARCHAR

後來編輯

免責聲明:這不是測試,因爲我沒有你的表結構和數據

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 
+0

+1 @Daniel感謝您的幫助和額外提示;我認爲你可能更多的是我正在尋找的東西(儘管在其他答案中使用'##'表格非常漂亮)。你是說我可以放下'東西',它仍然會運行?你有沒有時間簡化我的'SET @cols = ...'腳本並將簡化版本放入你的答案中? – whytheq 2013-02-19 15:38:10

+0

@whytheq查看更新的答案 – Daniel 2013-02-19 18:41:17

+0

感謝所有的幫助/建議 - 這一切似乎工作正常 - 我想我需要閱讀關於這個「FOR XML PATH」,因爲它看起來很強大 – whytheq 2013-02-20 09:31:10

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 '; 

這將創建臨時表的結果...

,如果你真的想之前選擇創建..

你需要收集列的類型,以建立創建表的陳述..

+3

這樣的'#xxx'執行動態SQL後,臨時表將不可用,從而挫敗了什麼運希望 – Lamak 2013-02-19 14:28:04

+0

目的啊..其真正的..對不起,@Lamak ..哼..將不得不使用## xxx使用這種方式 – Frederic 2013-02-19 14:45:30

+0

@Frederic - '##'很好的破解 - 我沒有看到它在 – whytheq 2013-02-19 15:21:46

2

Frederic是差不多 right -

動態SQL在與調用批次不同的範圍內執行。在動態SQL批處理中聲明的任何臨時對象(表,變量)只能在動態SQL批處理中使用。您將能夠SELECT INTO a 全球臨時表 - 因爲這些是連接特定的,並將持續在動態SQL批處理。

sp_executesql

+0

是的,我犯了一個小錯誤......我確實改變了使用全局臨時表... – Frederic 2013-02-19 14:52:18