大家好:
    以前做SQLSERVER开发的,刚刚转到ORACLE上来。
    我需要统计一个复杂的结果集。
    为了提高效率,我打算把一些中间结果放在一个类似临时表的表里面,然后再从这个临时表里面进行连接过滤等操作。    当然,我可以组合一个使用临时视图的复杂SQL来解决这个问题,但是这样处理起来麻烦,效率也很低。因此想在存储过程中处理。    请大家教教我:
1、如何创建临时表(或者类似的技术)
2、如何插入数据到临时表
3、存储过程中如何使用临时表(我试了以下,ORACLE的存储过程里面使用CREATE总是出错)
谢谢大家!最好给我一个完整的例子。

解决方案 »

  1.   

    EXECUTE IMMEDIATE 'CREATE .... '
      

  2.   

    zt
    需要创建一个临时表,请举例说明,谢谢!  
    ---------------------------------------------------------------  
     
    是TEMPORARY  
    CREATE  GLOBAL  TEMPORARY  TABLE  flight_schedule  (  
         startdate  DATE,    
         enddate  DATE,    
         cost  NUMBER)  
     
    ---------------------------------------------------------------  
     
    create  proecdure  name_pro  
    as  
    str  varchar2(100);  
    begin  
    str:='CREATE  GLOBAL  TEMPORARY  TABLE  TABLENAME  ON  COMMIT  PRESERVE  ROWS  as  select  *  from  others_table';  
    execute  immediate  str;  
    end;  
    /可以把临时表指定为事务相关(默认)或者是会话相关:
    ON COMMIT DELETE ROWS:指定临时表是事务相关的,Oracle在每次提交后截断表。
    ON COMMIT PRESERVE ROWS:指定临时表是会话相关的,Oracle在会话中止后截断表。=================
    可以创建以下两种临时表:
    1。会话特有的临时表
       CREATE GLOBAL TEMPORARY <TABLE_NAME> (<column specification>)
       ON COMMIT PRESERVE ROWS;
    ========
    对全局临时表的总结在临时表上的操作比在一般的表上的操作要快。因为:
    1创建临时表不需要往编目表中插入条目,临时表的使用也不需要访问编目表,因此也没有对编目表的争用。
    2仅有创建临时表的app才可存取临时表,所以在处理临时表时没有锁。
    3如果指定NOT LOGGED选项,在处理临时表时不记日志。所以如果有仅在数据库的一个会话中使用的大量临时数据,把这些数据存入临时表能大大提高性能。
    DECLARE GLOBAL TEMPORARY TABLE TT(C1 INT, C2 CHAR(20));
    在CONNECT RESET命令后,临时表不再存在。
    建临时表是动态编译的,所以对临时表的使用也必须放在DECLARE CURSER 后面
    CREATE PROCEDURE INSTT2(P1 INT, P2 CHAR(20))
    BEGIN
      DECLARE GLOBAL TEMPORARY TABLE TT(C1 INT, C2 CHAR(20)) %
      INSERT INTO SESSION.TT VALUES(P1, P2);
      BEGIN
        DECLARE C1 CURSOR WITH RETURN FOR SELECT * FROM SESSION.TT;
      END;
    END %2。事务特有的临时表
       CREATE GLOBAL TEMPORARY <TABLE_NAME> (<column specification>)
       ON COMMIT DELETE ROWS;
      
      在Oracle中,全局临时表并不会删除,实际上你只需要建立一次,以后直接应用就行了,这与MS和Sybase不一样。实际上在断开数据库连接时,临时表中数据自动清空,不同的Session之间是隔离的,不许要当心相互影响,不过如果起用了连接共享的话,你要用On Commit delete rows使数据仅在事物内部有效。
      

  3.   

    zt
    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
             2SQL> select * from admin_work_area;STARTDATE  ENDDATE    CLASS
    ---------- ---------- --------------------
    17-1&Ocirc;&Acirc; -03 17-1&Ocirc;&Acirc; -03 session temperary会话2:SQL> select * from permernate;         A
    ----------
             1
             2SQL> select * from admin_work_area; 未选择行.会话2看不见会话1中临时表的数据.
      

  4.   

    可是我有個一直弄不明白,也沒有在網上見到有任何說明的問題,就是:如果我在存儲過程中用動態SQL創建了一個臨時表,當第一次有某個用戶調用此存儲過程時,臨時表已創建,然後,稍後有另一個用戶再次調用此過程時(此時兩個或多個用戶同時調用此存儲過程),又會執行創建臨時表的動態SQL,這時會不會出現“表已存在”的錯誤????????????????????????這種情況該如何處理??????????????
      

  5.   

    zjp8310(z一阵风z) 
    會出現“表已存在”的錯誤你要先判断是否存在,存在就不需要建了
      

  6.   

    那這真是比Sql Server中麻煩多了!
      

  7.   

    CREATE   PROCEDURE   INSTT2(P1   INT,   P2   CHAR(20))
    BEGIN
        DECLARE   GLOBAL   TEMPORARY   TABLE   TT(C1   INT,   C2   CHAR(20));
    end
    不能编译通过啊
      

  8.   

    在写复杂的业务逻辑时,难免会用到临时表;临时表生成很少的日志,每种数据库又都会对其进行特定的处理,使它很适合保存中间结果集。
    SQL Server在存储过程中动态的创建、删除临时表,使用是很方便也是很常见的。Oracle的临时表是从当前登录用户的临时表空间分配存储空间,而在创建时不涉及存储空间的分配;而且临时表保存的数据只对当前会话可见。
    问题是,在Oracle存储过程中使用临时表时,是事先创建临时表,还是在存储过程中动态的创建、删除呢?
    针对不同的存储过程,因为要使用到的临时表字段个数以及数据类型等不尽相同,所以事先创建的临时表只能对某一个或者对某几个存储过程可以使用,那么针对不同的存储过程都事先创建临时表,如果存在较多的存储过程且逻辑复杂都要使用临时表,那麽数据库里会有很多事先创建的临时表。在存储过程中创建临时表,试图象SQL Server那样的方式随意的Insert、Update临时表,这样是行不通的。针对这个问题,有没有好的解决办法或者建议?