创建具有与现有表相同的表结构的Oracle临时表

时间:2019-03-23 16:48:59

标签: oracle oracle18c

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

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

3 个答案:

答案 0 :(得分:4)

Create global temporary table mytemp 
as 
select * from myTable
where 1=2

答案 1 :(得分:2)

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

因此,使用全局临时表的正确方法与我们在SQL Server中使用临时表的方法非常不同。 CREATE GLOBAL TEMPORARY TABLE语句是一次性的练习(就像其他任何表一样)。在Oracle中doesn't stop people wanting to do it,即时删除和重新创建表是不好的做法。

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


您已标记问题[oracle18c]。如果您真正使用的是Oracle 18c,则可以使用一个新功能,即私有临时表,该功能更接近SQL Server临时表。这些表是真正的内存表,并在事务或会话结束时(根据定义再次)自动删除。这些内容涵盖了in the Oracle documentation,但这些是标题。

使用来自永久表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中对临时表的需求大大减少。

答案 2 :(得分:2)

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

要在Oracle中实现完全相同的功能,可以使用private temporary tables

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属性不适用于该表类型。

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