• Oracle临时表GLOBAL TEMPORARY TABLE


    临时表:像普通表一样,有结构,但是对数据的管理上不一样,临时表存储事务或会话的中间结果集,临时表中保存的数据只对当前 会话可见,所有会话都看不到其他会话的数据,即使其他会话提交了,也看不到。临时表不存在并发行为,因为他们对于当前会话都是独立的。

    创建临时表时,Oracle只创建了表的结构(在数据字典中定义),并没有初始化内存空间,当某一会话使用临时表时,ORALCE会从当前用户的 临时表空间分配一块内存空间。也就是说只有向临时表中插入数据时,才会给临时表分配存储空间。
     
    临时表分事务级临时表和会话级临时表。 
    事务级临时表只对当前事务有效,通过语句:ON COMMIT DELETE ROWS 指定。 
    会话级临时表对当前会话有效,通过语句:ON COMMIT PRESERVE ROWS语句指定。 
      
    用法举例(在SCOTT模式下): 
    CREATE GLOBAL TEMPORARY TABLE session_temp_tab ON COMMIT PRESERVE ROWS AS SELECT * FROM emp WHERE 1=2;
     ON COMMIT PRESERVE ROWS语句指定所创建的临时表是会话级临时表,当我们断开连接或手动执行DELETE或TRUNCATE之前,临时表中的数据一直存
     在,并且只有当前会话可以看到,其他会话看不到。 
     
     CREATE GLOBAL TEMPORARY TABLE transaction_temp_tab ON COMMIT DELETE ROWS AS SELECT * FROM emp WHERE 1=2;
     ON COMMIT DELETE ROWS语句指定所创建的临时表是事务级临时表,当COMMIT或ROLLBACK之前,这些数据一直存在,当事务提交之后,表中数据自动清除。

      注意:事务级临时表必须在处理的时候提交事务(Commit),否则会报以下错误;  ORA-01410: 无效的 ROWID 

    insert into session_temp_tab select * from emp ; 
    insert into transaction_temp_tab select * from emp ;
     
     
     SQL> select count(*) from session_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            14 
     
     SQL> select count(*) from transaction_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            14 
    SQL> commit; 
     
     Commit complete 
     
     SQL> select count(*) from session_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            14 
     
     SQL> select count(*) from transaction_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            0 
     
     
    当COMMIT之后事务级临时表中的数据自动清除,所以再次查询的时候得到结果为0; 
    SQL> disconnect ; 
    Not logged on 
     
     SQL> connect scott/tiger ; 
    Connected to Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 
    Connected as scott 
     
     SQL> select count(*) from transaction_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            0 
     
     SQL> select count(*) from session_temp_tab ; 
     
     COUNT(*) 
    ---------- 
            0 
    当断开之后重新连接之后,会话级临时表中的数据也被自动删除了。

    ===============================================================================================

    5.tempporary 
    也是heap表的一种,有两种临时表。
    SQL> create global temporary table gt1 as select * from dba_objects;

    Table created.

    SQL> select * from gt1;--没有数据,因为省掉了on commit delete rows

    no rows selected
    SQL> create global temporary table gt2 on commit delete rows as select * from dba_objects;

    Table created.

    --还有一种临时表,在提交的时候保留数据
    SQL> create global temporary table gt3 on commit preserve rows as select * from dba_objects;

    Table created.

    SQL> select count(1) from gt3;

      COUNT(1)
    ----------
         10042
    --另一个CMD
    SQL> select count(1) from gt3;

      COUNT(1)
    ----------
             0
    这个表是实实在在的表,这个表结构任何一个SESSION都能看到。但是每个SESSION的数据都是隔离的。定义保留在数据字典,数据保存在临时表空间里。
    使用它减少对日志的产生。
    10g,创建这个表属于哪个用户,就缺省的放在这个用户缺省的临时表空间里。11g可以单独放在一个表空间里。

    ====================================================================================================

    在Oracle8i或以上版本中,可以创建以下两种临时表
    1。会话特有的临时表
        CREATE GLOBAL TEMPORARY <TABLE_NAME> (<column specification>)
        ON COMMIT PRESERVE ROWS;
     
    2。事务特有的临时表
        CREATE GLOBAL TEMPORARY <TABLE_NAME> (<column specification>)
        ON COMMIT DELETE ROWS;
       CREATE GLOBAL TEMPORARY TABLE MyTempTable
    所建的临时表虽然是存在的,但是你试一下insert 一条记录然后用别的连接登上去select,记录是空的,明白了吧,我把下面两句话再贴一下:
    --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行)
    --ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。
    冲突的问题更本不用考虑.
     
    临时表只是保存当前会话(session)用到的数据,数据只在事务或会话期间存在。
     
    通过CREATE GLOBAL TEMPORARY TABLE命令创建一个临时表,对于事务类型的临时表,
    数据只是在事务期间存在,对于会话类型的临时表,数据在会话期间存在。
     
    会话的数据对于当前会话私有。每个会话只能看到并修改自己的数据。DML锁不会加到
    临时表的数据上。下面的语句控制行的存在性。
      
    ● ON COMMIT DELETE ROWS 表名行只是在事务期间可见
    ● ON COMMIT PRESERVE ROWS 表名行在整个会话期间可见
     
    可以对临时表创建索引,视图,出发器,可以用export和import工具导入导出表的
    定义,但是不能导出数据。表的定义对所有的会话可见。


    Temporary Tables临时表
    1简介
       ORACLE数据库除了可以保存永久表外,还可以建立临时表temporary tables。这些临时表用来保存一个会话SESSION的数据,
       或者保存在一个事务中需要的数据。当会话退出或者用户提交commit和回滚rollback事务的时候,临时表的数据自动清空,
       但是临时表的结构以及元数据还存储在用户的数据字典中。
       临时表只在oracle8i以及以上产品中支持。
    2详细介绍
       Oracle临时表分为 会话级临时表 和 事务级临时表。
    会话级临时表是指临时表中的数据只在会话生命周期之中存在,当用户退出会话结束的时候,Oracle自动清除临时表中数据。
    事务级临时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束(commit or rollback),Oracle自动清除临时表中数据。
    临时表中的数据只对当前Session有效,每个Session都有自己的临时数据,并且不能访问其它Session的临时表中的数据。因此,
    临时表不需要DML锁.当一个会话结束(用户正常退出 用户不正常退出 ORACLE实例崩溃)或者一个事务结束的时候,Oracle对这个会话的
    表执行 TRUNCATE 语句清空临时表数据.但不会清空其它会话临时表中的数据.
    你可以索引临时表和在临时表基础上建立视图.同样,建立在临时表上的索引也是临时的,也是只对当前会话或者事务有效. 
    临时表可以拥有触发器.
    3建立临时表
       临时表的定义对所有会话SESSION都是可见的,但是表中的数据只对当前的会话或者事务有效.
       建立方法:
    1) ON COMMIT DELETE ROWS 定义了建立事务级临时表的方法.
    CREATE GLOBAL TEMPORARY TABLE admin_work_area
            (startdate DATE,
             enddate DATE,
             class CHAR(20))
          ON COMMIT DELETE ROWS;
    EXAMPLE:
    SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area
      2          (startdate DATE,
      3           enddate DATE,
      4           class CHAR(20))
      5        ON COMMIT DELETE ROWS;
    SQL> create table permernate( a number);
    SQL> insert into admin_work_area values(sysdate,sysdate,'temperary table');
    SQL> insert into permernate values(1);
    SQL> commit;
    SQL> select * from admin_work_area;
    SQL> select  * from permernate;
    A
    1
    2)ON COMMIT PRESERVE ROWS 定义了创建会话级临时表的方法.
    CREATE GLOBAL TEMPORARY TABLE admin_work_area
            (startdate DATE,
             enddate DATE,
             class CHAR(20))
         ON COMMIT PRESERVE ROWS;
    EXAMPLE:

    会话1:
    SQL> drop table admin_work_area;
    SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area
      2          (startdate DATE,
      3           enddate DATE,
      4           class CHAR(20))
      5       ON COMMIT PRESERVE ROWS;
    SQL> insert into permernate values(2);
    SQL> insert into admin_work_area values(sysdate,sysdate,'session temperary');
    SQL> commit;
    SQL> select * from permernate;

             A
    ----------
             1
             2

    SQL> select * from admin_work_area;

    STARTDATE  ENDDATE    CLASS
    ---------- ---------- --------------------
    17-1?? -03 17-1?? -03 session temperary

    会话2:

    SQL> select * from permernate;

             A
    ----------
             1
             2

    SQL> select * from admin_work_area;

    未选择行.

    会话2看不见会话1中临时表的数据.

    4 ORACLE临时表和SQLSERVER临时表异同

    SQLSERVER临时表
    也可以创建临时表。临时表与永久表相似,但临时表存储在 tempdb 中,当不再使用时会自动删除。
    有本地和全局两种类型的临时表,二者在名称、可见性和可用性上均不相同。本地临时表的名称以单个数字符号 (#) 打头;
    它们仅对当前的用户连接是可见的;当用户从 Microsoft? SQL Server? 2000 实例断开连接时被删除。全局临时表的名称以数学符号
    (##) 打头,创建后对任何用户都是可见的,当所有引用该表的用户从 SQL Server 断开连接时被删除。
    例如,如果创建名为 employees 的表,则任何人只要在数据库中有使用该表的安全权限就可以使用该表,除非它已删除。
    如果创建名为 #employees 的本地临时表,只有您能对该表执行操作且在断开连接时该表删除。如果创建名为 ##employees 的全局临时表
    ,数据表中的任何用户均可对该表执行操作。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果该表在您创建
    后有其他用户使用,则 SQL Server在所有用户断开连接后删除该表
    不同:
    1.        SQL SERVER临时表是一种”内存表”,表是存储在内存中的.ORACLE临时表除非执行DROP TABLE,否则表定义会保留在数据字典中.
    2.        SQL SERVER临时表不存在类似ORACLE临时表 事务级别 上的功能.
    3        SQL SERVER本地临时表(#) 与 ORACLE的会话级别临时表类似,但是在会话退出的时候,ORACLE不会删除表.
    4        SQL SERVER的全局临时表(##) 是指多个连接共享同一片内存.当没有指针引用该内存区域时,SQL SERVER自动释放全局临时表.
    5        由于ORACLE不是一种 内存中的数据库. 所以如果ORACLE类似SQL SERVER 频繁的对临时表进行建立和删除,必定会影响性能.
    所以ORACLE会保留临时表的定义直到用户DROP TABLE.
    6        在ORACLE中,如果需要多个用户共享一个表(类似SQL SERVER的全局临时表##).则可以利用永久表,
    并且在表中添加一些可以唯一标识用户的列.利用触发器和视图.当用户退出的时候,根据该登陆用户的唯一信息删除相应的表中的数据.
    这种方法给ORACLE带来了一定量的负载.

    ==================================================================================

    SQL的IN中有很多值,如何处理能提高效率?            

     

    近日碰到一个棘手的问题,从外部得到了一组ID数据,要跟Oracle中的某个表做比对,从Oracle中取出ID一样的数据。举个例子,pub有版主有会员,版主是会员的子集,版主名单存在Oracle里面,但会员名单没存在里面。假设pub在搞抽奖活动,一小时一次,中奖的会员名单通过中奖系统传给Oracle。我现在想把刚才中奖的会员中是版主的名单列出来,该怎么做。

          实际环境中,通过外部获得的数据数量级为K,Oracle的这个表数量级为几十K到上百K,比对效率成为一个关键因素。我能想到的方法就是构造多条SQL语句,把这些ID作为IN的列表值传进去(IN后的列表项不能超过1000个,故可能会需要多个sql)。

          带着问题咨询了yangtingkun ,得到的答复是效率不会太高也不会太低,Oracle可能会做全表扫描,但效率比你一个一个去比对肯定要快了。实际执行了一下,IN里面传了300个参数,得到执行计划如下(做的是 INDEX RANGE SCAN):

    执行计划
    ----------------------------------------------------------
    Plan hash value: 1656459801

    -----------------------------------------------------------------------------
    | Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |         |   284 |  1136 |     1   (0)| 00:00:01 |
    |   1 |  INLIST ITERATOR  |         |       |       |            |          |
    |*  2 |   INDEX RANGE SCAN| XXXXXX|   284 |  1136 |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------

           拼多个sql语句是麻烦一点,不过这样做效率上没啥问题。想想也是,总比我将数据插入表,通过表关联去做要方便一些,因为建表的话我毕竟还需要对表里的数据进行维护。

          “哦,这样的话,你建一个临时表吧!”
          “global temporary table?”
          “嗯,这表就是专门用来解决这样的问题的!临时数据只管往里面插,可通过on submit关键字设置为会话有效或者事务有效,各会话间互相看不到数据,不会互相影响。”

            哈哈,原来问题这么简单啊!省去了数据维护的麻烦,得到了表关联带来的高效数据处理,唯一会影响到效率的问题就是往临时表里插数据了,一条一条显然很慢了,考虑用存储过程来实现,呵呵。

     插入多行数据,使用union

                   DB.ExcuteNonQuery("Delete from t863_Y_UKIDS_XL");
                    sSqlInsertTemp = "INSERT INTO  t863_Y_UKIDS_XL(iukid) " + sXLsqlvalue;

    INSERT INTO  t863_Y_UKIDS(iukid)

    SELECT  123   FROM  DUAL
     UNION SELECT  456   FROM  DUAL
     UNION SELECT  1233   FROM  DUAL
     UNION SELECT  4526   FROM  DUAL
     UNION SELECT  12333   FROM  DUAL
     UNION SELECT  456   FROM  DUAL

  • 相关阅读:
    3、生成证书请求文件
    2、申请苹果App ID
    登录iOS Dev Center
    SQL Server 合并行
    asp 月末 月初
    linux
    ASP数组全集,多维数组和一维数组[转]
    oracle 秒
    oracle 存储过程 包 【转】
    linux
  • 原文地址:https://www.cnblogs.com/coolsundy/p/4546896.html
Copyright © 2020-2023  润新知