存储过程不从db2中删除记录

时间:2015-03-19 16:52:49

标签: sql stored-procedures db2

CREATE OR REPLACE PROCEDURE  WRK.PURGE_ACH_BATCH_TAB_1()
LANGUAGE SQL

BEGIN
    -- Declare cursor
    DECLARE v_CNT_BLOCK INTEGER;
    DECLARE Ac_no BIGINT;
    DECLARE SQLSTATE CHAR(5) DEFAULT '00000'; 
    DECLARE mycur cursor for 
        SELECT t.TNX_Ac_no
        FROM WRK.BATCH_TAB1 c
            INNER JOIN WRK.BATCH_TAB t
                ON c.BATCH_ID = t.BATCH_ID
                    AND c.PROCESS_ID = t.process_ID
        WHERE c.BATCH_START_TS < (CURRENT DATE -7 days); 

    set v_CNT_BLOCK = 0;
    open mycur;

    FETCH FROM mycur INTO Ac_no;
    WHILE(SQLSTATE = '00000') DO
        DELETE FROM WRK.BATCH_TAB1 b WHERE b.TNX_Ac_no = Ac_no;
        SET v_CNT_BLOCK=v_CNT_BLOCK+1;
        if v_CNT_BLOCK >= 5 then
            set v_CNT_BLOCK = 0;
            commit;
        end if;

        FETCH FROM mycur INTO Ac_no;  

    END WHILE; 

    CLOSE mycur; 

    commit; 

END
@ 

我在db2表中有19条记录,以满足分配给游标的条件,执行此操作后获取成功命令,但没有从db中删除任何值。请帮助我在哪里错过了什么。

2 个答案:

答案 0 :(得分:1)

您似乎正在尝试从光标正在读取的同一个表中删除。根据您运行的隔离级别,可能会出现锁定错误。

在您的示例代码中,似乎没有任何理由首先使用游标。你应该删除该集。

DELETE 
FROM WRK.BATCH_TAB1 c
WHERE EXISTS (SELECT 1 FROM WRK.BATCH_TAB t
               WHERE c.BATCH_ID = t.BATCH_ID
                 AND c.PROCESS_ID = t.process_ID
             )
AND c.BATCH_START_TS < (CURRENT DATE -7 days); 

鉴于评论中相关性的修正:

DELETE 
FROM WRK.BATCH_TAB1 c
WHERE EXISTS (SELECT 1 FROM WRK.BATCH_TAB t
               WHERE c.BATCH_ID = t.BATCH_ID
                 AND c.PROCESS_ID = t.process_ID
                 AND t.BATCH_START_TS < (CURRENT DATE -7 days)
             );

或者,如果您必须使用游标,原因在于您的示例中不明显的原因,那么您应该查看DELETE语句的“定位形式”:

DELETE FROM WRK.BATCH_TAB1 WHERE CURRENT OF CURSOR mycur;

删除光标刚刚返回的记录。当然,使用INNER JOIN对原始光标不起作用。但是,如果您使用上面我的答案中的WHERE EXISTS语法,则定位删除将是一个选项。

答案 1 :(得分:1)

在最新的DB2版本上,您应该可以执行以下操作:

BEGIN
 DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
 loop1: WHILE SQLSTATE = '00000' DO
  DELETE FROM (
   SELECT FROM WRK.BATCH_TAB1 c
   WHERE EXISTS (SELECT 1 FROM WRK.BATCH_TAB t
               WHERE c.BATCH_ID = t.BATCH_ID
                 AND c.PROCESS_ID = t.process_ID
                 AND t.BATCH_START_TS < (CURRENT DATE -7 days)
   ) FETCH FIRST 5 ROWS ONLY
  );
  IF SQLSTATE = '02000' THEN -- not found
   LEAVE loop1;
  END IF;
  COMMIT;
 END WHILE;
END@