存储过程总结

存储过程的一般结构如下:

CREATE PROCEDURE testDynamicCursor(IN flag CHAR(1))   --首句定义名称及参数
BEGIN  --开始
   DECLARE v_sql VARCHAR(1000);  --定义变量
   DECLARE v_st STATEMENT;
   DECLARE v_cursor CURSOR WITH RETURN FOR v_st;  -- 定义游标(不同的数据库写法可能不一样)
   --下面是处理过程(处理过程里面也可以继续定义变量或游标,继续处理)
   IF (flag = '1') THEN
    SET v_sql = 'SELECT * FROM TEST1';
  ELSE
    SET v_sql = 'SELECT * FROM TEST2';
  END IF;
  
   PREPARE v_st FROM v_sql;
   OPEN v_cursor;
END  --结束

使用存储过程的难点在于游标的使用,本文着重介绍游标的使用。
使用游标对记录集循环进行处理的时候一般操作如以下几个步骤:
1、把记录集传给游标(定义游标)
2、打开游标
3、开始循环
4、从游标中取值
5、检查那一行被返回
6、处理
7、关闭循环
8、关闭游标

一、ORCAL的游标
1.其游标的遍历有两种:
⑴For 循环游标
   循环游标隐式打开游标,自动滚动获取一条记录,并自动创建临时记录类型变量存储记录。处理完后自动关闭游标。
     For  变量名  In  游标名 
     Loop
      数据处理语句;
     End Loop;
   ⑵Loop循环游标
     。。。
    Loop
     Fatch  游标名InTo  临时记录或属性类型变量;
     Exit  When   游标名%NotFound;
    End   Loop;
实例:
loop遍历:
Declare
     Cursor myCur is select ename,job,sal,empno from emp;
     varE myCur%rowType;
  Begin
     if myCur%isopen = false then
        open myCur;
       dbms_output.put_line('Opening...');
     end if;
     loop
        fetch myCur into varE;
        exit when myCur%notfound;
        dbms_output.put_line(myCur%rowCount||'    '||vare.empno||'    '||vare.ename||'    '||vare.sal);
     end loop;
     if myCur%isopen then
        Close myCur;
        dbms_output.put_line('Closing...');
     end if;
  End;

for遍历:
Declare
     Cursor myCur is select * from emp;
  Begin
     for varA in myCur
      loop
         dbms_output.put_line(myCur%rowCount||'    '||varA.empno||'    '||varA.ename||'  '||varA.sal);
      end loop;
  End;

二、DB2游标
有两种定义方式:
注意 commit和rollback
使用游标时要特别注意如果没有加with hold 选项,在Commit和Rollback时,该游标将被关闭。Commit 和Rollback有很多东西要注意。特别小心。
1.第一种
declare continue handler for not found
   begin
   set v_notfound = 1;
   end;
declare cursor1 cursor with hold for select market_code from tb_market_code for update;
open cursor1;
set v_notfound=0;
fetch cursor1 into v_market_code;
while v_notfound=0 Do
--work
set v_notfound=0;
fetch cursor1 into v_market_code;
end while;
close cursor1;
这种方式使用起来比较复杂,但也比较灵活。特别是可以使用 with hold 选项。如果循环内有commit或rollback 而要保持该cursor不被关闭,只能使用这种方式。

注:实际上这种还有些复杂,可以简化:

begin

declare .......   --定义游标;

open .... ---开启游标;

while   ....  do

fetch cursor1 into v_market_code;

----work;

<!-- 另一个游标  start -->

p1:begin

declare ......

.......

end p1;

<!-- 另一个游标  end -->

end while;

colse ....  --关闭游标

end;
2.第二种
pcursor1: for loopcs1 as cousor1 cursor as
select market_code as market_code
   from tb_market_code
   for update
   do
   end for;
   这种方式的优点是比较简单,不用(也不允许)使用 open,fetch,close。
但不能使用with hold 选项。如果在游标循环内要使用commit,rollback则不能使用这种方式。如果没有commit或rollback的要求,推荐使用这种方式(看来For这种方式有问题)。

修改游标的当前记录的方法
update tb_market_code set market_code='0' where current of cursor1;
不过要注意将cursor1定义为可修改的游标
declare cursor1 cursor for select market_code from tb_market_code
for update;

for update 不能和 GROUP BY、 DISTINCT、 ORDER BY、 FOR READ ONLY及UNION, EXCEPT, or INTERSECT 但 UNION ALL除外)一起使用。

实例:
CREATE OR REPLACE PROCEDURE "WGHYXXM_2"."PROC_SQL_ADDR"
()
LANGUAGE SQL
SPECIFIC SQL191014013422827
BEGIN
--特别注意:过程中循环游标时,while语句就是循环,所以要去掉loop
  declare np_addrs VARCHAR(30);
  declare rel_org VARCHAR(30);
  declare p_addrs cursor with hold FOR SELECT cust_id from GD_P_CUST_ADDR_HIS where cust_location_bd is NULL;
  open p_addrs;
 -- LOOP
  fetch p_addrs into np_addrs; --所有地址为空的客户
  while np_addrs is not null DO
        begin
        DECLARE rel_loc_db CURSOR for SELECT BRANCH_ID from GD_P_CUST_MANGER_BRANCH_REL where CUST_ID = np_addrs;
        open rel_loc_db;
      --  LOOP
        fetch rel_loc_db into rel_org;
        while rel_org is not null DO
                begin
                declare cust_dbx NUMERIC ;
                declare cust_dby NUMERIC;
                declare loc_dbs cursor with hold for SELECT db2gse.st_x(LOCATION_BD) , db2gse.st_y(LOCATION_BD) from FND_BANK_INFO where ORG_ID = rel_org;
                open loc_dbs;
             --   LOOP
                fetch loc_dbs into cust_dbx , cust_dby;
                while cust_dbx is not null do
                        BEGIN
                        UPDATE GD_P_CUST_ADDR_HIS set CUST_LOCATION_BD = db2gse.st_POINT(cust_dbx , cust_dby,1) where CUST_ID = np_addrs;
                        end;
                end while;
              --  end loop;
                close loc_dbs;
                end;
        end while;
      --  end loop;
        close rel_loc_db;
        end;
  end while;
 -- end LOOP;  
  close p_addrs;
END

-- CALL dbms_output.put_line('111');  这是打印输出
-- execute test_select3_procedure('XXX'); 执行存储过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值