2

如何创建与现有表具有相同表结构的全局临时表?

我知道这个概念在 SQL 服务器中可用,例如“从 abc 中选择 * 到 #temp123”。但我想在 Oracle 中执行相同的操作。

4

3 回答 3

4
Create global temporary table mytemp 
as 
select * from myTable
where 1=2
于 2019-03-23T17:16:27.510 回答
3

Oracle 中的全局临时表与 SQL Server 中的临时表有很大不同。它们是永久数据结构,只是其中的数据是临时的(仅限于会话或事务,取决于表的定义方式)。

因此,正确使用全局临时表的方式与我们在 SQL Server 中使用临时表的方式有很大的不同。CREATE GLOBAL TEMPORARY TABLE 语句是一次性练习(与任何其他表一样)。动态删除和重新创建表在 Oracle 中是不好的做法,但这并不能阻止人们这样做

鉴于全局临时表的创建应该是一次性的练习,使用 CREATE TABLE ... AS SELECT 语法并没有真正的好处。该语句应该被显式定义,并且脚本应该像任何其他 DDL 一样存储在源代码控制中。


您已标记您的问题[oracle18c]。如果您真的在使用 Oracle 18c,那么您将拥有一个新功能,即私有临时表,它更接近 SQL Server 临时表。这些是真正在内存中的表,并在事务或会话结束时自动删除(再次根据定义)。这些都包含在 Oracle 文档中,但这里是头条新闻。

使用永久表中的数据子集创建私有临时表数据T23

create table t23  (
    id number primary key
    , txt varchar2(24)
    );

insert into t23 
select 10, 'BLAH' from dual union all 
select 20, 'MEH' from dual union all 
select 140, 'HO HUM' from dual
/


create private temporary table ORA$PTT_t23 
on commit preserve definition
as 
select * from t23
where id > 100;

前缀是强制性的ORA$PTT(虽然可以通过设置 init.ora 参数 PRIVATE_TEMP_TABLE_PREFIX 来更改,但何必呢?

之后我们可以在表上执行任何常规 DML:

select * from ORA$PTT_t23;

最大的限制是我们不能在静态 PL/SQL 中使用该表。该表在数据字典中并不存在,因此 PL/SQL 编译器会抛出异常——即使对于匿名块:

declare 
    rec t23%rowtype;
begin
    select * 
    into rec
    from ORA$PTT_t23';
    dbms_output.put_line('id = ' || rec.id);
end;
/

ORA-06550:第 6 行,第 10 列:PL/SQL:ORA-00942:表或视图不存在

在 PL/SQL 中对私有临时表的任何引用都必须使用动态 SQL 完成:

declare 
    n pls_integer;
begin
    execute immediate 'select id from ORA$PTT_t23' into n;
    dbms_output.put_line('id = ' || n);
end;
/

基本上,这将它们的使用限制为 SQL*Plus(或运行一系列纯 SQL 语句的sqlcl脚本。因此,如果您有一个适合的用例,那么您应该检查私有临时表。但是,请考虑 Oracle 是与 SQL Server 在很多方面都不同,尤其是它的多版本一致性模型:读者不阻塞写者,因此 Oracle 中对临时表的需求要少得多。

于 2019-03-24T13:38:23.430 回答
2

在 SQL Server 的语法中,表名中的前缀“#”(哈希)#temp123表示 - 创建只能通过当前会话访问的临时表(“##”表示“全局”)。

要在 Oracle 中实现完全相同的目标,您可以使用私有临时表

SQL> show parameter private_temp_table            

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
private_temp_table_prefix            string      ORA$PTT_

create table mytab as 
    select 1 id, cast ('aaa' as varchar2 (32)) name from dual
;

create private temporary table ora$ptt_mytab on commit preserve definition as
    select * from mytab where 1=0
;
Private TEMPORARY created.

之后,您可以在 SQL 和 PL/SQL 块中使用这些表:

declare
    r mytab%rowtype;
begin 
    insert into ora$ptt_mytab values (2, 'bbb');
    select id + 1, name||'x' into r from ora$ptt_mytab where rownum = 1;
    insert into ora$ptt_mytab values r;
end;
/
select * from mytab
union all
select * from ora$ptt_mytab;

        ID NAME                            
---------- --------------------------------
         1 aaa                             
         2 bbb                             
         3 bbbx                            

私有临时表的一些重要限制:

  • 名称必须始终以参数定义的任何内容作为前缀PRIVATE_TEMP_TABLE_PREFIX。默认值为ORA$PTT_.

  • 您不能在命名的 PL/SQL 块(例如包、函数或触发器)的静态语句中引用 PTT。

  • %ROWTYPE属性不适用于该表类型。

  • 您不能使用默认值定义列。

于 2019-03-24T13:56:03.580 回答