Sybase开发人员问:如何在Oracle中创建临时表?

4

我熟悉Sybase/SQL Server,可以像这样创建临时表:

SELECT * 
INTO   #temp
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey

SELECT * 
FROM   #temp 
WHERE  field1 = 'value' 

#temp仅在此会话期间存在,只能被我看到。

我想在Oracle中做类似的事情,但我正在阅读有关“全局临时表”的内容,听起来不像是同一件事。

我该如何在Oracle中执行与Sybase相同的操作?

谢谢 :)

6个回答

4
您的第一步应该是将其作为单个查询执行:
SELECT * 
FROM   
(
SELECT * 
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey
)
WHERE  field1 = 'value';

对于非常复杂的情况或者temp#非常大的情况,可以尝试使用子查询分解子句,可选地使用materialize提示:

with #temp as
(
SELECT /*+ materialize */ 
       * 
FROM   tab1 , 
       tab2 
WHERE  tab1.key = tab2.fkey
)
SELECT * 
FROM   temp#
WHERE  field1 = 'value';

如果这不太有帮助,可以选择全局临时表的方法。

4

全局临时表不同,定义在会话结束后仍然存在,而且该表(但不包括数据)对所有会话可见。

如果您正在编写存储过程,是否考虑过游标?这是一种更复杂但非常高效和清晰的处理临时数据集的方式。


Sybase用户通常出于性能原因避免使用游标。我不确定这在历史上是否是真的,但现在已经不是这种情况了,或者是否有正当理由,但在使用Oracle时肯定不是一个问题。 - Stephen Darlington
顶级回答。感谢光标建议。我想我必须找到一种方法来使用全局临时表。它可能有其优点。我只需要弄清楚它们是什么!;) - AJ.
你可能会从不每次创建表中获得轻微的性能提升 :)另一件事是,在您的第一个示例中,如果您只想从两个表中获取每个一个列,您可能需要考虑使用视图。 - Colin Pickard

2

Oracle没有直接提供这种功能的类似物。全局临时表相似,但必须事先创建,并且由于锁定问题,在后续更改可能会很困难。

大多数此类需求可以通过游标或不同的PL/SQL集合类型(嵌套表、变长数组、关联数组)来满足,但这些都不能像表一样使用。也就是说,您无法从它们中选择。


1

我认为全局临时表是一样的。它们将为您提供对临时表的私有访问权限,当会话结束时,该表将被删除:

全局临时表中的数据是私有的,这意味着只有插入数据的会话才能访问该数据。全局临时表中特定于会话的行可以保存整个会话,或仅保存当前事务。ON COMMIT DELETE ROWS子句表示在事务结束时应删除数据。

在进一步阅读问题后,我认为主要区别,也许是您的问题在于临时表在会话之间持久存在。因此,在Oracle中,确切的等效方式可能是:

CREATE GLOBAL TEMPORARY TABLE my_temp_table ON COMMIT DELETE ROWS select * from other table;

即使其中的数据不再存在,该表将一直存在,直到被删除,即使通过会话。相反,您需要提前创建临时表。


1
我不会说它们是完全相同的,因为你必须显式地创建和删除全局临时表,但据我所知,它们是用于此目的的最佳 Oracle 功能。 - Dave Costa
实际上,ON COMMIT PRESERVE ROWS 更接近他想要的,因为他的 Sybase 表会在会话的其余时间存在。ON COMMIT DELETE ROWS 将在事务结束时截断(类似于回滚)。 - Colin Pickard

1

在Oracle中,临时表模型略有不同,其核心是“CREATE GLOBAL TEMPORARY TABLE…”语句。临时表定义始终是全局的,但数据始终私有于会话,并且数据是否跨提交保留取决于指定“on commit preserve rows”或“on commit delete rows”的限定符。

我有一些Perl脚本和一篇博客文章,探讨了Oracle临时表的特定行为,请参阅我的博客


0

是的,Carson说得对。全局临时表只对创建它们的会话可见,并在第一次提交或回滚时消失,或在会话结束时消失。您可以在创建全局临时表时设置。


严格来说:插入表中的数据仅对会话可见,并在事务或会话结束时消失。该表对模式中的任何会话都是可见的。这就是为什么它是“全局”的原因。 - Dave Costa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接