如何在Oracle中将select语句的结果存储到临时表中?

3

在SQL Server中,我们可以使用select column1,column2 into #temp from tableName的语法实现相应功能。但是,在Oracle数据库中,我无法写出同样的查询语句。

我想在Oracle数据库中将select/insert/delete/update或任何结果集存储到本地临时表中,我该如何实现这一功能呢?

我正在Oracle SQL Developer工具中执行以下查询:

select * into #temp 
from bmi;

但是我遇到了以下错误,请帮忙找出错误原因。

当我在Microsoft SQL Server中执行相同的查询时,它被执行并创建了一个临时表(#temp table),该表不存在于数据库中,但它可以为该特定会话保存数据。所以我想在ORACLE数据库中实现相同的场景。

ORA-00911: 无效字符 00911. 00000 - "无效字符" *原因:标识符不能以除字母和数字以外的任何ASCII字符开头。第一个字符后也允许使用$#_。用双引号括起来的标识符可以包含除双引号以外的任何字符。替代引号(q'#...#')不能将空格、制表符或回车作为分隔符。对于所有其他上下文,请参阅SQL语言参考手册。 *操作: 错误行:1 列:15


#temp 只用于 SQL Server,用于存储临时信息。对于 Oracle,有一个全局临时表用于当前会话。它是持久定义,但不包含数据。全局临时表中的数据不会被清除或回滚。 - venkatesh
1
在Oracle中,全局临时表是一种永久表。它们唯一的临时之处在于数据。只有插入数据的会话才能看到该数据,并且当会话结束时,数据会被自动删除。 - venkatesh
在Oracle中,通常不需要像在SQL Server中那样使用临时表。只需使用派生表或子查询即可。 - user330315
PL/SQL的select into用于填充标量变量,例如,select max(salary) into l_salary from employees将会用最高薪水的值填充标量变量l_salary。正如错误信息所示,变量名不能以#开头。 - William Robertson
3个回答

4
我想将select/insert/delete/update或任何结果集存储到Oracle数据库的本地临时表中,但这是不可能的。Oracle没有本地临时表,它的内部模型与SQL Server非常不同,因此许多SQL Server实践在Oracle中是不必要的。关键的洞察力是:你不想将select/insert/delete/update或任何结果集存储到本地临时表中。在T-SQL中,这是为了实现某些业务逻辑而必须执行的操作。但实际上,在SQL Server中您想要做的事情以及在Oracle中您想要做的事情是编写一些代码,为您的组织提供价值。因此,有了这种思维方式,您需要做什么呢?
如果您想循环遍历结果集,那么也许游标循环是您正在寻找的?
for rec in ( select * from some_table
             where the_date = date '2018-02-01' )
loop
    ...

如果您想在将数据插入数据库之前对其进行处理,那么您可以使用PL/SQL集合

type l_recs is table of some_table%rowtype;

也许你只需要了解Oracle的事务管理模型。在纯SQL中,很多事情都是可能的,而不需要任何过程性框架。


1
Oracle 18,最近发布的版本,确实支持所谓的"私有临时表",这些表仅在事务(或会话,可选)的持续时间内存在。新的语法在此处描述:https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/CREATE-TABLE.html#GUID-F9CE0CC3-13AE-4744-A43C-EAC7A71AAAB6 - Carlo Sirna
@carlosirna - 非常有趣,谢谢你的建议。根据我的经验,很少有组织机构使用最新版本的Oracle(或任何企业平台)。事实上,许多地方仍在使用不支持和被弃用的11g版本或更早的版本。 - APC
我在“新功能指南”中也遇到了这个问题。但是,除非我漏掉了什么,否则它仍然需要动态SQL,所以你从中获得的只是能够创建一个临时表并使用固定名称而不与其他会话冲突的能力。在11g中,你可以使用生成的表名来做同样的事情,例如'MY_GTT#'||sys_context('userenv','sessionid') - William Robertson

1
创建临时表

create global temporary table 
results_temp (column1, column2)
on commit preserve rows;

然后从您的表中插入到它:
insert into results_temp (column1, column2 )
SELECT column1,column2 
FROM source_table

嗨 user7294900, - sandesh jogi
我不想创建表,只是想将结果存储在临时表中,以便在同一会话中进一步使用。谢谢...... - sandesh jogi
使用第二个SQL语句,进行一个简单的插入操作,使用SELECT语句。 - Ori Marko
请您看一下我之前编辑过的问题,这样我就能从您那里得到答案了。 - sandesh jogi
不要使用#,只需将临时表的名字写出来(如果不存在就创建它),写成select * into temp from bmi - Ori Marko

0
create global temporary table temp_table_name
on commit preserve rows as select column1,column2,columnN from your_table;

嗨,谢谢你的回答,但是当我执行你的查询时,表被创建了,但是我不想创建这个表,我只想要一个临时表来保存查询结果,并且在同一个会话中继续使用这个临时表。我正在使用ORACLE数据库。我希望在不创建表的情况下将结果存储在临时表中。 - sandesh jogi
请您看一下我之前编辑过的问题,这样我就能从您那里得到答案了。谢谢。 - sandesh jogi
GLOBAL TEMPORARY表具有持久的定义,但数据不是持久的,并且全局临时表不会生成重做或回滚信息。例如,如果您正在处理大量行,而这些结果在当前会话结束时不再需要,那么您应该将表创建为临时表:创建全局临时表 results_temp (...) 在提交时保留行; - venkatesh
1
@sandeshjogi:获取临时表的唯一方法就是创建一个临时表。 - user330315
2
请解释你做了什么。避免只给出代码答案。 - GGO

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