【delphi+oracle报表解决方案(二)】临时表的使用
关键字:oracle,delphi,报表,临时表,存储过程注:delphi 6 + oracle8.1.6一.临时表基本概念下面部分摘取csdn网友的内容
"臨時表的概念:
臨時表是那些只在事務處理或者會話進行期間存在數據的表,數據會在事務處理或者會話開始以後插入臨時表,當事務處理或會話完成之後就會刪除。
臨時表按照數據存在的方式分爲兩種A. 針對事務處理的臨時表,即事務處理後就數據會刪除(如:DDL語句後,COMMIT後),定義的語法是:
CREATE GLOBAL TEMPORARY TABLE TRANSACTION_TAB ON COMMIT DELETE ROWS AS …(結果集)
B. 針對會話的臨時表,即會話完成之後才刪除數據,定義的語法是:
CREATE GLOBAL TEMPORARY TABLE TRANSACTION_TAB ON COMMIT PRESERVE ROWS AS …(結果集)
臨時表可以建立索引,視圖,觸發器(用來保證數據的完整性)等本人理解的:
PRESERVE临时表与永久表的区别:
永久表在不同会话呈现相同的数据(不考虑事务处理),当所有事务完全提交时,不同应用程序看到的永久表 数据是完全相同。
而对于PRESERVE临时表,现在system创建此类型临时表temptbl ,用户a通过应用程序appa访问oracle,用户b通过应用程序appb访问oracle,
则a修改temptbl后,它的结果只在a中可见。此时b中的看到的temptbl不会随a修改temptbl而改变。
举例
temptbl只有一个字段a
 运行两上sql /plus程序,分别简称为甲,已
甲中 insert temptbl  values('11');
已中insert temptbl values ('da');
再在甲,已窗口中分别运行select * from temtbl 看到结果如下:
甲窗口
a
11已窗口
a
da也就是说创建一个PRESERVE临时表的话,实际在访问oracle的每个应用程序中都会存在一个此临时表,并且操作互不影响.
二.临时表在做报表时如何使用
有时候碰到这种情况,要做的报表做视图时用一条sql语句写要 几百行 来写,即使写出来了,是正确的,但维护不太可能。
要做到可维护,就必须将任务分解来做,代码程序化控制,思路清晰。
要达到上述目的实现起来思路其实很简单:
首先创建一个临时表,临时表的结构与你要生成的报表的结构一致,然后往这个临时表中填数据,可以添加数据集到临时表,可以添加一行记录到临时表,可以修改临时表某行某列的值
可能一个存储过程几百行,但写起来十分容易,就象在前台delphi中写程序一样.举例如下: 表介绍:
 输电线路表  JCCLine 字段如下:
LINE_CODE   线路代码
LINE_NAME  线路名称
Vol_LEVEL 电压等级
说明:电压等级取值只有1100kv , 380kv, 220kv 三种
      一条输电线路上有多个设备(EQUIP)。当线路上的设备检查出缺陷时 会进行缺陷(BUG)记录  设备缺陷记录表  JCCEQUIP_BUG_REC 字段如下:
  LINE_CODE 线路代码
  EQUIP_CODE 设备代码
  BUG_LEVEL  缺陷级别
  FIND_DATETIME  发现缺陷的时间
  说明:缺陷级别只可能为 I,II ,III 一种.我们记录的是设备缺陷级别,现在要统计 线路的级别,方法如下:(注意*线路级别*跟 *设备缺陷级别*是两个概念)
  如果该线路上 的设备 没有出现缺陷 ,则该线路评为I级;
  如果该线路上 只要有一个设备 的缺陷纪录是III级,则该线路评为 III级;
  如果该线路上 只要有一个设备 的缺陷纪录是II级,则该线路评为 II级如果要统计某段时间的线路评级,则方法与上类似:
  如果 这段时间 该线路上 的设备 没有出现缺陷 ,则该线路评为I级;  
  ..下略如果要统计各电压等级 的 评级,则方法与上类似
  如果该 电压等级的 所有线路的 这段时间 的设备 没有出现缺陷 ,则该线路评为I级; 
  ..下略所需数据按如下建立:
create table JCCLINE ( LINE_CODE VARCHAR2(50),
LINE_NAME VARCHAR2(50),
                VOL_LEVEL VARCHAR2(50) );
INSERT INTO JCCLINE values('LINE_CODE1','LINE_NAME1','1100v');
INSERT INTO JCCLINE values('LINE_CODE2','LINE_NAME2','380v');
INSERT INTO JCCLINE values('LINE_CODE3','LINE_NAME3','220v');
commit;CREATE TABLE JCCEQUIP_BUG_REC( LINE_CODE VARCHAR2(50),
EQUIP_CODE VARCHAR2(50),
BUG_LEVEL VARCHAR2(50),
FIND_DATE DATE) ;
INSERT INTO JCCEQUIP_BUG_REC values('LINE_CODE1', 'EQUIP_CODE1','I', TO_DATE('2003-8-15','YYYY-MM-DD'));
INSERT INTO JCCEQUIP_BUG_REC values('LINE_CODE1', 'EQUIP_CODE2','II', TO_DATE('2003-8-16','YYYY-MM-DD'));
INSERT INTO JCCEQUIP_BUG_REC values('LINE_CODE1', 'EQUIP_CODE3','III', TO_DATE('2003-9-25','YYYY-MM-DD'));
commit;现在统计 2003年 8-1到 9-1号各 电压等级 的评级:
按理应得到如下报表:电压等级  级别  缺陷个数
1100v    II   2
380v       I      0
220v       I      0
方法如下:
1.根据报表 的结构 创建一个 相应结构的preserve临时表
create table jcctemptbl (电压等级 varchar2(50),
级别 varchar2(50),
缺陷个数 number(10,0) ) 2.编写包过程,存入参数为 起始时间,终止时间,存出参数 为一游标,用来返回临时表的内容,我们要得到的报表的内容就在临时表里面。
create or replace package JCCTEST_TEMPTBL
AS
  TYPE RC_TYPE IS REF CURSOR ;
  PROCEDURE GET_VOL_LEVEL(dt_Begin IN VARCHAR2 ,dt_end IN VARCHAR2 , result_rc out RC_TYPE) ;
END ;CREATE OR REPLACE package BODY JCCTEST_TEMPTBL
AS
  PROCEDURE GET_VOL_LEVEL(dt_Begin IN VARCHAR2 ,dt_end IN VARCHAR2, result_rc out RC_TYPE)
  IS
  --将要求的值 一个个求出来,然后再往临时表里面插
     LEVEL_1100 VARCHAR2(50) ;   --1100V的评级级别
     BUGCOUNT_1100 NUMBER(10,0) ;--1100v的缺陷个数
     BUGREC_1100III_COUNT NUMBER(10,0) ; --  1100v三级缺陷设备的个数
     BUGREC_1100II_COUNT NUMBER(10,0) ; --  1100v二级缺陷设备的个数
     LEVEL_380 VARCHAR2(50) ;   --380V的评级级别
     BUGCOUNT_380 NUMBER(10,0) ;--380v的缺陷个数
     BUGREC_380III_COUNT NUMBER(10,0) ; --  380v三级缺陷设备的个数
     BUGREC_380II_COUNT NUMBER(10,0) ; --  380v二级缺陷设备的个数
     LEVEL_220 VARCHAR2(50) ;   --220V的评级级别
     BUGCOUNT_220 NUMBER(10,0) ;--220v的缺陷个数
     BUGREC_220III_COUNT NUMBER(10,0) ; --  220v三级缺陷设备的个数
     BUGREC_220II_COUNT NUMBER(10,0) ; --  220v二级缺陷设备的个数
  BEGIN
    delete from jcctemptbl  ;
    --求1100v中III级设备个数
    select to_number(count(*)) into  BUGREC_1100III_COUNT
       from JCCLINE A ,
            JCCEQUIP_BUG_REC B
       WHERE ((A.LINE_CODE = B.LINE_CODE)
          --     AND (TRIM(A.VOL_LEVEL) = '1100v')
       -- and b.BUG_LEVEL = 'III' 
       -- and (TO_DATE(FIND_DATE,'YYYY-MM-DD') >=TO_DATE(dt_Begin,'YYYY-MM-DD'))
     AND (FIND_DATE <=TO_DATE(dt_END,'YYYY-MM-DD'))) ;
    --求1100v中II级设备个数
    select count(*) into  BUGREC_1100III_COUNT
       from JCCLINE A ,
            JCCEQUIP_BUG_REC B
       WHERE A.LINE_CODE = B.LINE_CODE
               AND TRIM(A.VOL_LEVEL) = '1100v'
        and b.BUG_LEVEL = 'II' 
        and FIND_DATE>=TO_DATE(dt_Begin,'YYYY-MM-DD')
AND FIND_DATE <=TO_DATE(dt_END,'YYYY-MM-DD') ;
   select DECODE( SIGN(BUGREC_1100III_COUNT-1), 1,'III',
               DECODE(SIGN(BUGREC_1100III_COUNT-1),1,'II' ,'I'
                     )
           ) 
      INTO LEVEL_1100  FROM DUAL;
     --求求1100v中缺陷记录的数目
    select count(*) into  BUGREC_1100III_COUNT
       from JCCLINE A ,
            JCCEQUIP_BUG_REC B
      WHERE A.LINE_CODE = B.LINE_CODE
               AND TRIM(A.VOL_LEVEL) = '1100v' 
              and FIND_DATE >=TO_DATE(dt_Begin,'YYYY-MM-DD')
       AND FIND_DATE <=TO_DATE(dt_END,'YYYY-MM-DD') ;
    insert into jcctemptbl values('1100v', LEVEL_1100 , BUGREC_1100III_COUNT) ;
   --380v,220v的求法如上类似,求出后继续插入临时表中,此处略
   
   --通过游标返回临时表中的数据
   open result_rc for
     select * from jcctemptbl ;
  END ;
END ;
/一句话,有了临时表 写后台就跟写前台一样,不过临时表会带来oracle的速度问题,权横一下,复杂报表用这个东西肯定值得.注:如果存储过程的输入参数设为date,在前端我将相应参数也设为相应的date类型时会出错,故此设为varchar2,到时候多转化一次即可.2  pl/sql developer 可以进行存储过程的单步调试,用了就会离不开它
   query reporter 作视图快,可视化设计视图
   以述两种工具网上有下载,很容易上手
  
本人水平有限,有错误之处请指正!

解决方案 »

  1.   

    写完代码没检查就发上来,抱欠!谢谢楼上的指正!
    怎么才能把顶贴改过来?*******************************************************
    *******************************************************
    【【【【顶贴有误,修改如下】】】】】
    【【【【顶贴有误,修改如下】】】】】
    【【【【顶贴有误,修改如下】】】】】
    *******************************************************
    *******************************************************【错误地方】
    二.中创建临时表的语句,
    """"""
    方法如下:
    1.根据报表 的结构 创建一个 相应结构的preserve临时表
    create table jcctemptbl (电压等级 varchar2(50),
    级别 varchar2(50),
    缺陷个数 number(10,0) ) 
    """""
    我用的创建永久表,应改为创建preserve型临时表
    将创建语句改为:
    【修改内容】
    create global temporary table jcctemptbl (电压等级 varchar2(50),
    级别 varchar2(50),
    缺陷个数 number(10,0) ) 
                            on commit preserve rows ;
      

  2.   

    结贴
    能加FAQ吗?
    我要分