2012-01-18 58 views
5

我正在使用Oracle 11g全局臨時表,因爲我需要一個解決方案,我可以將行添加到臨時表以進行連接,並且我只希望將行添加到臨時表中包括Oracle Connection/session。我在Oracle中使用全局臨時表,因爲我希望表存在於會話之間,所以每次創建查詢時都不必重新創建表。這工作很好。全球臨時表 - SQL Server與Oracle

的My Oracle表的定義如下:

CREATE GLOBAL TEMPORARY TABLE book_id_temp 
( 
    book_id RAW(32) 
)ON COMMIT DELETE ROWS; 

我有相同的數據庫結構也在SQL Server 2008 R2側,並需要在SQL Server中的一個類似的解決方案。我想:

  1. 打開SQL連接(ADO.NET)
  2. 中的事務:
  3. - 添加行臨時表。
  4. - 在另一個表上加入它們,選擇結果
  5. - 只有在此會話期間添加的行纔會包含在聯接中。另一個線程可能在同一個臨時表上執行。那麼當地的臨時表可能是最好的嗎?
  6. 回滾整個交易。

從我讀過的SQL Server中的全局臨時表中,這些表在連接結束後存在,就像常規表一樣,並且像Oracle中的全局臨時表一樣。但是,數據的範圍並不明確。只有創建行的SQL Server會話才能訪問它,就像在Oracle中一樣? SQL Server全局臨時表的數據可訪問性是什麼?你有一個替代方案來達到我的目標嗎?

+0

Oracle全局臨時表也需要截斷,取決於操作...我會使用SQL Server中臨時表的一個表變量給定的選擇,但你需要解釋您在連接丟失時獲得持久性的需求以獲得真正的幫助。爲什麼不製作一個真正的桌子? – 2012-01-18 15:38:35

+0

我希望表格在會話之間存在,所以每次創建查詢時都不必重新創建表格。 – 2012-01-18 15:41:10

+0

它*聽起來像是你想要一個本地臨時表,而不是全局臨時表。你能描述一下你所需要的語義嗎? – 2012-01-18 15:46:27

回答

6

Oracle中的臨時表是持有會話本地臨時數據的永久對象。 SQL Server中的臨時表是臨時對象。

  1. 在SQL Server中,全局臨時表保存所有會話都可見的數據。 「全局臨時表對任何用戶和任何創建後的連接都是可見的。」 http://msdn.microsoft.com/en-us/library/ms186986.aspx
  2. 全局臨時表仍是不能無限期保留的臨時對象,可能需要在使用前創建。 「當引用表的所有用戶與SQL Server實例斷開連接時,將刪除全局臨時表...」。 http://msdn.microsoft.com/en-us/library/ms186986.aspx

我發現本地臨時表或表變量與Oracle的全局臨時表最接近,最大的區別是您必須每次都創建它。

通常,像你這樣的情況下,第3步,行添加到臨時表中,將通過執行select ... into #temp_table_name ....(相當於甲骨文create table ... as select ...http://msdn.microsoft.com/en-us/library/ms188029.aspx

也可以做,你不能這樣做在下面存儲過程:(僞代碼)

begin proc 
    call another proc to create local temp table. 
    use temp table 
end proc 

本地臨時表在從創建它們的存儲過程返回時被銷燬。

更新2014-10-14:本地臨時表的行爲在SQL Server的並行數據倉庫版本中不同。在創建它們的存儲過程退出時,臨時表不會被刪除,而是繼續存在於會話的其餘部分。這種行爲觀察到:

select @@version 
Microsoft SQL Server 2012 - 10.0.5108.1 (X64) Jun 24 2014 20:17:02 Copyright (c) Microsoft Corporation Parallel Data Warehouse (64-bit) on Windows NT 6.2 <X64> (Build 9200:) 
1

如果手動創建在tempdb數據庫中的表,你acheive或多或少相同的效果:

USE tempdb; 

CREATE TABLE foo... 

,然後解決這些問題:

select * from tempdb..foo 

這些表將不會在會話間被刪除。您需要手動截斷它們,不能等同於ON COMMIT DELETE ROWS。

+0

我目前的ADO.NET實現是在將記錄插入臨時表並執行連接之後,我在IDbConnection上執行Rollback(),因此實際上可能已足夠。你說表格不會被刪除,但是它的內容呢?我在想,如果我從來沒有真正進行交易,沒有其他活動連接甚至可以訪問數據。 – 2012-01-18 16:00:50

+0

它會工作,但效率非常低。 SQL Server中的回滾非常容易出錯並且速度很慢,特別是對於大型數據。使用會話級別的臨時表或者如果你堅持有一個全局表,在完成後截斷它,會更有效率。 – 2012-01-18 16:18:00

1

如果您在SQL Server中創建全局臨時表(## table),它將'生存'並且可以通過其他會話訪問,直到該會話關閉。另外,在原始會話關閉之前,您將不能爲同一名稱創建不同會話的全局臨時表,您會發現該表已存在。爲了您的目的,Global Temp Table不是一個好的解決方案。

本地臨時表(#表)會好得多,並將實現您正在尋找的東西。

希望這有助於SQL Server上

+0

是全局臨時表的記錄,只能在創建它們的事務中訪問?我寧願不必爲每個查詢創建表。 – 2012-01-18 17:04:48

+0

否,SQL Server全局臨時表(## table_name)中的記錄對所有會話均可見。 – 2012-01-18 17:15:39

4

臨時表默認情況下局部。會話結束後,表格將被刪除。如果執行如下腳本:

create table #Foo (
     FooID int 
     ,FooCode1 varchar (20) 
) 

insert table #Foo (FooID, FooCode1) 
values (1001, 'X') 

insert table #Foo (FooID, FooCode1) 
values (1002, 'Y') 

select f.FooID 
     ,f.FooCode1 
     ,b.BarID 
     ,b.BarCode1 
    from #foo f 
    join bar b 
    on bar.FooID = f.FooID -- (or whatever predicate) 

查詢將只返回在此會話中插入到#Foo中的內容的行。 #Foo是會話本地的;您可以使用自己的#Foo臨時表進行多個會話,而不必擔心命名空間衝突。當會話關閉時,臨時表將被丟棄。如果您使用持久數據庫連接(例如,客戶端 - 服務器桌面應用程序),則也可以在完成之後明確放置#Foo。

+0

我創建一個IDbConnection並管理事務(不是持久的)並關閉連接。當連接關閉時,會話也是如此,對嗎? – 2012-01-18 16:32:46

+0

是的,如果關閉連接,會話將關閉。 – ConcernedOfTunbridgeWells 2012-01-18 17:04:33