Oracle临时表


详细讲解Oracle数据库中的临时表用法

这篇文章主要介绍了Oracle数据库中的临时表用法,希望对大家的学习和工作有所帮助。 



一:语法 



在Oracle中,可以创建以下两种临时表: 


        (1) 会话特有的临时表 



           (2) 事务特有的临时表 




所建的临时表虽然是存在的,但是如果insert 一条记录然后用别的连接登上去select,记录是空的。   


--ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行) 


--ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。  

 


二:动态创建 




create or replace procedure pro_temp(v_col1 varchar2,v_col2 varchar2) as

v_num number;

begin

select count(*) into v_num from
user_tables where table_name=''T_TEMP'';

--create temporary table 

if v_num<1 then

execute immediate ''CREATE GLOBAL TEMPORARY TABLE T_TEMP (

COL1 VARCHAR2(10),

COL2 VARCHAR2(10)

) ON COMMIT delete ROWS'';

end if;

--insert  data 

execute immediate ''insert into t_temp values
(''''''  v_col1  '''''',''''''  v_col2  '''''')'';

execute immediate ''select col1 from t_temp'' into v_num;

dbms_output.put_line(v_num);

execute immediate ''delete from t_temp'';

commit;

execute immediate ''drop table t_temp'';

end pro_temp;



  


测试:   


15:23:54 SQL> set serveroutput on

15:24:01 SQL> exec pro_temp(''11'',''22'');

11

PL/SQL 过程已成功完成。

已用时间: 00: 00: 00.79

15:24:08 SQL> desc t_temp;

ERROR:

ORA-04043: 对象 t_temp 不存在



三:特性和性能(与普通表和视图的比较) 




临时表只在当前连接内有效 


临时表不建立索引,所以如果数据量比较大或进行多次查询时,不推荐使用 


数据处理比较复杂的时候时表快,反之视图快点 


在仅仅查询数据的时候建议用游标: open cursor for ''sql clause'';
 

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

 

临时表特性

1、数据库中的所有会话均可以访问同一临时表,但只有插入数据到临时表中的会话才能看到它本身插入的数据。

2、可以把临时表指定为事务相关(默认)或者是会话相关:

3、如果临时表中有记录的话,是无法删除表的。即无法drop table

4、虽然临时表不产生 "REDO" ,但却是要产生 "UNDO" 

临时表的分类及创建

1、会话特有的临时表

记录将留在此表中,直到会话断开或通过DELETETRUNCATE从物理上删除这些记录。

CREATE GLOBAL TEMPORARY TABLE <TABLE_NAME> (<column specification> )

ON COMMIT PRESERVE ROWS;

2、事务特有的临时表

当事务提交后,在事务之中插入的记录不会被保留,自动删除。

CREATE GLOBAL TEMPORARY TABLE <TABLE_NAME> (<column specification> )

ON COMMIT DELETE ROWS;

3DDL语法注释

这里的“GLOBAL”表示临时表的定义,是所有会话都能看见的。建立临时表只有 CREATE GLOBAL TEMPORARY TABLE,而没有其它CREATE ****** TEMPORARY TABLE形式的命令。

临时表的删除

1、删除会话特有的临时表

想快速删除此类临时表,必须先truncate表中的数据,然后drop表结构。如果使用DELETE命令先删除表中记录的话,还无法直接删除表。只有等当前会话退出后,在其它会话或新的会话中删除表结构。

使用DELTETEDROP表报错:

SQL> DELETE tmp_test;

8 rows deleted

SQL> commit;

Commit complete

SQL> drop table tmp_test;

ORA-14452: attempt to create, alter or drop an index on temporary table already in use

这是因为用“ON COMMIT PRESERVE ROWS”子句时,会加行锁(ROW-X).

TYPE=TO

TO Lock "Temporary Table Object Enqueue"

具体请看DOC ID:186854.1

2、删除事务特有的临时表

ON COMMIT DELETE ROWS 子句就不会有那么多限制。COMMIT以后,记录自动清除,可以直接就删除表。

临时表的表空间的分配

临时表在创建的时候,是不分配表空间的。当用户使用临时表存储数据时,从该用户默认的临时表空间来分配存储空间。

参考资料

1http://blog.itpub.net/post/10/8764

使用临时表的sql优化案例二-临时表的统计信息

2http://www.itpub.net/178008.html&highlight=%C1%D9%CA%B1%B1%ED

抛砖引玉:三种主流数据库中临时表的使用.doc

MS SQLSERVER

SQL Server 支持临时表。临时表就是那些名称以井号 (#) 开头的表。如果当用户断开连接时没有除去临时表,SQL Server 将自动除去临时表。临时表不存储在当前数据库内,而是存储在系统数据库 tempdb 内。

临时表有两种类型:

本地临时表:本地临时表的名称以单个数字符号 (#) 打头;它们仅对当前的用户连接是可见的;当用户从 Microsoft SQL Server 2000 实例断开连接时被删除。

全局临时表:全局临时表的名称以数学符号 (##) 打头,创建后对任何用户都是可见的。如果在创建全局临时表的连接断开前没有显式地除去这些表,那么只要所有其它任务停止引用它们,这些表即被除去。当创建全局临时表的连接断开后,新的任务不能再引用它们。当前的语句一执行完,任务与表之间的关联即被除去;因此通常情况下,只要创建全局临时表的连接断开,全局临时表即被除去。

例如,如果创建名为 employees 的表,则任何人只要在数据库中有使用该表的安全权限就可以使用该表,除非它已删除。如果创建名为 #employees 的本地临时表,只有您能对该表执行操作且在断开连接时该表删除。如果创建名为 ##employees 的全局临时表,数据表中的任何用户均可对该表执行操作。如果该表在您创建后没有其他用户使用,则当您断开连接时该表删除。如果该表在您创建后有其他用户使用,则 SQL Server在所有用户断开连接后删除该表。

现在,临时表的许多传统用途可由具有 table 数据类型的变量替换。

ORACLE

Oracle支持临时表。临时表用来保存事务或会话期间的中间结果。在临时表中保存的数据只有对当前会话是可见的,任何会话都不能看到其他会话的数据,即使在当前会话COMMIT数据以后也是不可见的。多用户并行不是问题,一个会话从来不阻塞另一个会话使用临时表。即使锁定临时表,一个会话也不会阻塞其他会话使用临时表。临时表比正常表产生的REDO少得多,然而,由于临时表必须产生包含数据的UNDO信息,所以会产生一定数量的REDO日志。

临时表将从用户临时表空间的的目前日志中分配空间,或者如果从有定义权的程序中访问,将使用程序所有者的临时表空间。全局临时表实际上只是表本身的模板。创建临时表的行为不包括存储空间的分配,也不包括INITIAL的分配。因此,在运行时当一个会话首先将数据放到临时表中时,这时将创建这个会话的临时段。由于每个会话获取自己的临时段,每个用户可能在不同的表空间中为临时表分配空间。USER1default临时表空间为TEMP1,他的临时表将从TEMP1中分配空间,USER2default临时表空间为TEMP2,他的临时表将从TEMP2中分配空间。

临时表在每个数据库中只需创建一次,不必在每个存储过程中创建。临时表总是存在的,除非手动的删除他。临时表作为对象存在数据字典中,并且总是保持为空,直到有会话在其中放入数据。Oracle允许创建基于临时表的视图和存储过程。

临时表可以是以会话为基础的,也可以是以事务为基础的。ON COMMIT PRESERVE ROWS子句使临时表成为基于会话的模式。行将留在此表中,直到会话断开或通过DELETETRUNCATE从物理上删除这些行。ON COMMIT DELETE ROWS子句使临时表成为基于事务的模式。当会话提交后,行消失。这个临时表的自动清除过程不会有额外的开销。

oracle中,应用程序需要的临时表应该在程序安装时创建,而不是在程序运行时创建。(这是与ms sqlserversybase的使用的不同)

在任何数据库中,临时表的一个缺点是:事实上优化器在临时表中没有真正的统计功能。然而,在oracle中,一系列较好的统计猜测可以通过DBMS_STATS包在临时表中设置。

DB2

可使用 DECLARE GLOBAL TEMPORARY TABLE 语句来定义临时表。DB2的临时表是基于会话的,且在会话之间是隔离的。当会话结束时,临时表的数据被删除,临时表被隐式卸下。对临时表的定义不会在SYSCAT.TABLES中出现

下面是定义临时表的一个示例:

DECLARE GLOBAL TEMPORARY TABLE gbl_temp

LIKE empltabl

ON COMMIT DELETE ROWS

NOT LOGGED

IN usr_tbsp

此语句创建一个名为 gbl_temp 的用户临时表。定义此用户临时表 所使用的列的名称和说明与 empltabl 的列的名称和说明完全相同。隐式定义 只包括列名、数据类型、可为空特性和列缺省值属性。未定义所有其他列属性,包括唯一约束、外部关键字约束、触发器和索引。执行 COMMIT 操作时, 若未对该表打开 WITH HOLD 游标,则该表中的所有数据都被删除。不记录 对用户临时表所作的更改。用户临时表被放在指定的用户临时表空间中。此表空间必须存在,否则此表的声明将失败。

户定义临时表不支持:

LOB 类型的列(或基于 LOB 的单值类型列)

用户定义类型列

LONG VARCHAR 

DATALINK 

End of document.

 





Oracle临时表用法的比较


临时表是复杂SQL性能优化中常见手段,总结一下。

  

1) Global Temporary 句     分为会话级和事务级两种。

  

             会话级的临时表

    【语法】

 Create Global Temporary Table Table_Name    (the aggregation SQL statement) On Commit Preserve Rows

    【特点】

               临时表数据自动清空后,但是临时表的结构以及元数据还存储在用户的数据字典中。表的定义对所有的会话可见。

               临时表不需要DML锁。  www.2cto.com 

               可以索引临时表和在临时表基础上建立视图。

               在临时表上的索引也是临时的,也是只对当前会话或者事务有效。

               临时表可以拥有触发器。

               可以用export和import工具导入导出临时表的定义,但是不能导出数据。

   【适用场合】

              当某一个SQL语句多表关联,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中。

              程序执行过程中多次使用的临时数据,这些数据在整个程序的会话过程中都需要用的等等。

    【清除时点】

               当某一个SESSION退出之后自动清除数据(表结构保留)

    【不足】

               不支持lob对象,这也许是设计者基于运行效率的考虑,但实际应用中确实需要此功能时就无法使用临时表了。

               不支持主外键关系。

        

    例子: 

  CREATE GLOBAL TEMPORARY TABLE my_temporary

       (birthdate DATE,

        enddate   DATE,

        name CHAR(20)) ON COMMIT PRESERVE ROWS;


             事务级的临时表   

    【语法】

                Create Global Temporary Table Table_Name   

                   (the aggregation SQL statement) On Commit Delete Rows; 

    【清除时点】  当执行COMMIT之后自动清除数据(表结构保留)

     其他方面与会话级的临时表相同,不再列出。


2) with句


      准确的说with语句不叫临时表,但它与临时表使用概念上非常接近,同样列出。

     【语法】

    WITH

                     subquery_name

                  AS

                    (the aggregation SQL statement)

                  SELECT

                    (query naming subquery_name);


    【特点】

               附着于一个SQL 语句,也只对一个SQL语句产生作用。

               可以同时生成几张临时表。

               生存期极短,易于管理。

    【适用场合】

                Global Temporary 的适用场合都适用,只是针对一个SQL的场合

                特别方便融入常量或集合运算结果,有简化SQL的作用。

    【清除时点】

                查询完成后立即清除(数据及表结构)。

    例子: 

   WITH

      sum_sales AS

        ( select /*+ materialize */

          sum(quantity) all_sales from stores ),

      number_stores AS

        ( select /*+ materialize */

          count(*) nbr_stores from stores ),

      sales_by_store AS

        ( select /*+ materialize */

        store_name, sum(quantity) store_sales from

        store natural join sales )

      SELECT

         store_name

      FROM

         store,

         sum_sales,

         number_stores,

         sales_by_store

      where

         store_sales > (all_sales / nbr_stores)

  

    (注:使用/*+ materialize */让Oracle基于cost-based(基于成本)的优化策略生成临时表。  )

原文地址:https://www.cnblogs.com/ios9/p/9352910.html