【问题标题】:Creation of Oracle temporary table with same table structure to that of a existing table创建与现有表具有相同表结构的 Oracle 临时表
【发布时间】:2019-03-23 16:48:58
【问题描述】:

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

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

【问题讨论】:

    标签: oracle oracle18c


    【解决方案1】:
    Create global temporary table mytemp 
    as 
    select * from myTable
    where 1=2
    

    【讨论】:

      【解决方案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 中对临时表的需求要少得多。 p>

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 私有临时表是在 18c 中引入的
        • @BobC 我知道,这个话题被标记为 18c。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 2019-04-04
        相关资源
        最近更新 更多