2012-05-18 39 views
3

我正在爲SQL Server 2008編寫一個存儲過程,其中需要從一組表中提取信息。我不知道那些表格的結構。在同一個數據庫中還有另一個表,告訴我該表中字段的名稱和類型。訪問在不同範圍內創建的SQL Server臨時表

我這樣做:

declare @sql nvarchar(max) 

set @sql = 'select ... into #new_temporary_table ...' 
exec sp_executesql @sql 

Then I iterate doing: 

set @sql = 'insert into #another_temporary_table ... select ... from #new_temporary_table' 
exec sp_executesql @sql 

之後,我刪除臨時表。這發生在一個循環中,所以這個表格會被創建,填充和刪除多次,每次都有不同的列。

這失敗,出現錯誤:

Invalid object name: #new_temporary_table.

一些谷歌上搜索,我發現之後:

  1. #new_temporary_table在調用的範圍創建exec sp_executesql該表是從不同我的存儲過程之一。這是下一個exec sp_executesql找不到表的原因。這篇文章解釋它: http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/1dd6a408-4ac5-4193-9284-4fee8880d18a

  2. 我可以使用全球臨時表,這是前##前。我不能這樣做,因爲多個存儲過程可以同時運行,它們會影響對方的狀態

  3. 在這篇文章中說如果我發現自己在這種情況下我應該改變數據庫的結構。這是不是一種選擇對我來說: http://www.sommarskog.se/dynamic_sql.html

一個解決辦法我已經找到了所有的select into #new_temporary_table..和所有的insert into ...腳本組合成一個巨大的聲明。這工作正常,但它有一些缺點。

例如,如果我打印@sql來排除故障,文本會被截斷。

我還有其他的選擇嗎?所有想法都歡迎。

+0

爲什麼不能像'#new_temporary_table_1'你的臨時表使用不同的名稱。另外,既然你正在放棄它們......你可以使用普通表格(staging table);在tempdb下創建它們。所以即使你錯過了放棄它們,它們也會自動消失。 – Rahul

+0

你總結了很好的選項 - 「本地」臨時表(只在同一範圍內可見),全局臨時表,常規表 - 就是這樣。一種解決方案可能是在特定的模式下創建真實表格 - 存儲的特效同意;例如第一個存儲過程會創建'temp1'模式並將數據存儲在那裏,然後其他「屬於一起」的模式將全部使用該'temp1'模式作爲其表。第二次運行會使用'temp2'模式 - 依此類推... –

回答

1

我認爲最好使用一個腳本。

您可以更改在工具>選項>查詢結果> SQL Server>結果到文本中打印的字符數 - 將「最大字符數......」從256更改爲最大值(8192)。

如果它大於8192,那麼是的,打印很困難。但在這種情況下,您可以嘗試不同的選項。取而代之的PRINT @sql;改用以下(含結果到網格):

SELECT sql FROM (SELECT @sql) AS x(sql) FOR XML PATH; 

現在,您可以點擊結果,並在一個新的查詢窗口中打開。那麼這是一個XML文件窗口,你不能執行它或看到顏色編碼,你必須忽略它改變,例如>改爲>以使其作爲XML數據有效,但從這裏可以很容易地看到,如果你只是想要眼球。您可以將其複製並粘貼到真正的查詢編輯器窗口中,然後執行搜索並根據您的喜好替換已授權的字符。 FWIW我問他們做出這樣的XML窗口真正的查詢窗口,但這個被拒絕:

http://connect.microsoft.com/SQLServer/feedback/details/425990/ssms-allow-same-semantics-for-xml-docs-as-query-windows

+0

這個設置正是我需要的!我認爲8192足以解決問題。 – j0aqu1n

1

#temp表(不是全局)在它們創建的範圍和下面可用。 所以你可以做這樣的事情......

while (your_condition = 1) begin 
    set @sql = 'select ... into #temp1 ...from blah 
     exec sp_do_the_inserts' 
    exec(@sql) 
end 

的sp_do_the_inserts可能看起來像......

select * into #temp2 from #temp1 
....your special logic here.... 

這是假設你創建sp_do_the_inserts事前,當然。 不知道這是否符合您的需求。

3

你可以使用全局臨時表,但使用上下文ID如NEWID())作爲全局臨時表名的一部分。

declare @sql varchar(2000) 
declare @contextid varchar(50) = convert(varchar(20), convert(bigint, substring(convert(binary(16), newid()), 1, 4))) 
set @sql = 'select getdate() as stuff into ##new_temporary_table_' + @contextid 
exec (@sql) 
+1

這聽起來不錯。我甚至可以使用當前會話ID(@@ SPID) – j0aqu1n