全局临时表-SQL Server与Oracle



我使用Oracle 11g全局临时表,因为我需要一个解决方案,在该解决方案中,我可以向临时表中添加行以进行联接,并且我只希望包括添加到临时表中用于Oracle连接/会话的行。我在Oracle中使用全局临时表,因为我希望该表存在于会话之间,这样就不必每次创建查询时都重新创建它。这一切都很顺利。

我的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全局临时表的数据可访问性是什么?你有实现我目标的替代方案的建议吗?

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 ....(相当于Oracle 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的Parallel Data Warehousev版本中,本地临时表的行为有所不同。临时表在从创建它们的存储过程退出时不会被丢弃,而是在会话的其余部分继续存在。在上观察到的这种行为

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: )
默认情况下,SQL Server上的临时表是本地的。会话结束后将删除该表。如果您执行以下脚本:
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后显式删除它。

如果您在tempdb数据库中手动创建表,您或多或少会获得相同的效果:

USE tempdb;
CREATE TABLE foo...

然后寻址:

select * from tempdb..foo

这些表不会在会话之间删除。不过,您需要手动截断它们,而不是等效于ON COMMIT DELETE ROWS。

如果在SQL Server中创建全局临时表(##表),则该表将"活动",并且可以通过其他会话访问,直到该会话关闭为止。此外,在原始会话关闭之前,您将无法为不同的会话创建相同名称的全局临时表,您会发现该表已经存在。就您的目的而言,全局温度表不是一个好的解决方案。

本地临时表(#Table)会更好,并将实现您想要做的事情。

希望这能帮助

最新更新