日期:2014-05-17  浏览次数:20862 次

求一个参数游标的问题
各位大侠:
  我最近在写一个存储过程,具体的作用是每天把前一天的入库的记录数统计一下,然后和再前一天的比较一下,以此判断每天的入库进程是否正常。
我的数据库是Oracle9i Enterprise Edition Release 9.2.0.4.0
运行在AIX5.2的系统上。
现在写到一半,遇到一个问题,是关于参数游标的。
create or replace procedure p_wk_xdjk2 
AS 
v_smscontent varchar2(200) :='';
v_date varchar2(8);
v_date_before varchar2(8);

v_yyyy1 varchar2(4);
v_yy1 varchar2(2);
v_mm1 varchar2(2);
v_dd1 varchar2(2); 

v_yyyy2 varchar2(4);
v_yy2 varchar2(2);
v_mm2 varchar2(2);
v_dd2 varchar2(2); 


CURSOR c_jk (v_mma IN varchar2,v_dda IN varchar2,v_mmb IN varchar2,v_ddb IN varchar2) IS 
SELECT A.ZS,DECODE(TRUNC(ROUND((A.ZS-B.ZS)/B.ZS*100,2)),0,REPLACE(ROUND((A.ZS-B.ZS)/B.ZS*100,2),'0','0.'),TRUNC(ROUND((A.ZS-B.ZS)/B.ZS*100,2)))||'%' TBZR
FROM (SELECT COUNT(*) ZS FROM TG_CDR03_FIX_REAL PARTITION(P03)) A,(SELECT COUNT(*) ZS FROM TG_CDR03_FIX_REAL PARTITION(P01)) B;

vr_jk c_jk%ROWTYPE;
BEGIN
SELECT to_char(sysdate,'yyyy'),to_char(sysdate,'yy'),to_char(sysdate,'mm'),to_char(sysdate,'dd'),to_char(sysdate-1,'yyyy'),to_char(sysdate-1,'yy'),to_char(sysdate-1,'mm'),to_char(sysdate-1,'dd') into v_yyyy1, v_yy1,v_mm1,v_dd1,v_yyyy2, v_yy2,v_mm2,v_dd2 from dual;

  OPEN c_jk(v_mm1,v_dd1,v_mm2,v_dd2);
  LOOP
  FETCH c_jk INTO vr_jk;
  EXIT WHEN c_jk%NOTFOUND;
  v_smscontent := v_smscontent||v_dd2 ||vr_jk.ZS||':'||vr_jk.TBZR||';';
  END LOOP;
  v_smscontent := ''||'日:'||' '||v_smscontent;
  CLOSE c_jk;
insert into jzl_smsyx_ss@wkibm VALUES('13000000000',v_smscontent,'WK');
commit;/*插入短信*/
EXCEPTION
  WHEN OTHERS THEN
  ROLLBACK;
  insert into jzl_smsyx_ss@wkibm VALUES ('13000000000','详单监控存储过程失败。','WK');
  commit;
END;

如各位所见,其余部分都可以不管,关键是我写的那个游标。
CURSOR c_jk (v_mma IN varchar2,v_dda IN varchar2,v_mmb IN varchar2,v_ddb IN varchar2) IS 
SELECT A.ZS,DECODE(TRUNC(ROUND((A.ZS-B.ZS)/B.ZS*100,2)),0,REPLACE(ROUND((A.ZS-B.ZS)/B.ZS*100,2),'0','0.'),TRUNC(ROUND((A.ZS-B.ZS)/B.ZS*100,2)))||'%' TBZR
FROM (SELECT COUNT(*) ZS FROM TG_CDR03_FIX_REAL PARTITION(P02)) A,(SELECT COUNT(*) ZS FROM TG_CDR03_FIX_REAL PARTITION(P01)) B;
因为像TG_CDR03_FIX_REAL PARTITION(P02),这样的分区表,按我上面写的是没有问题的。可以顺利编译并执行成功。但是实际上,该表的03表示的是月份,而它是按日期来分区的。也就是说TG_CDR03_FIX_REAL PARTITION(P02)代表3月2日的入库量。所以我的游标必须要用参数变量来代替固定值,否则我就要每天重建我的存储过程。
现在的问题是TG_CDR03_FIX_REAL PARTITION(P02) 或者 TG_CDR03_FIX_REAL PARTITION(P01))这两个表名,当我用上面的参数v_mma IN varchar2,v_dda IN varchar2,v_mmb IN varchar2,v_ddb IN varchar2进行替代的时候,比如TG_CDRv_mma_FIX_REAL PARTITION(Pv_dda)存储过程能够编译成功,但是执行结果却是“详单监控存储过程失败”。

请各位大侠帮忙看看,因为我看到书上面的例子,游标是可以带参数的,不过例子中变量都是单独放在“=”符号的右侧的,像我这么写是不是不可以?


------解决方案--------------------
动态游标~!!!!
SQL code

 create   or   replace   procedure   SP_CLEAR(V_TABLE   IN   STRING)   IS  
   
      TYPE   cur_type   IS   REF   CURSOR;  
      c_tab   cur_type;  
      v_str   STRING(2000);  
      v_tab   t_clear.wlbmc%TYPE;  
      v_sql   STRING(3000);  
   
   
  begin  
      --Get   table   from   v_table  
      --Reorder   these   tables  
      v_str:=upper(v_table);  
      v_str:=REPLACE(v_str,',',''',''');  
      v_str:=''''||v_str||'''';  
      v_sql:='SELECT   WLBMC   FROM   T_CLEAR   WHERE   TRIM(WLBMC)   IN   ('||v_str||')   ORDER   BY   BZ   DESC';  
      OPEN   c_tab   FOR   v_sql;  
      LOOP  
          FETCH   c_tab   INTO   v_tab;  
          EXIT   WHEN   c_tab%NOTFOUND;  
          v_sql:='delete   from   '||v_tab||'';  
          EXECUTE   IMMEDIATE   v_sql;      
      END   LOOP;        
      COMMIT;      
      --deal   with   exception    
      EXCEPTION    
          WHEN   OTHERS   THEN  
                ROLLBACK;  
                RAIS