2012-01-18 45 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