db2存储过程 - 麻烦批处理DELETE语句

时间:2014-02-07 21:42:23

标签: sql loops cursor db2 commit

我只编写了几天的DB2过程,但试图在给定的表上进行“批量删除”。我的预期逻辑是:

  • 打开游标
  • 一直走到EOF
  • 在每次迭代时发出DELETE

为了简化这个问题,假设我只想在WHILE循环完成后发出一个COMMIT(所有DELETE)(即一旦光标到达EOF)。所以给出下面的代码示例:

CREATE TABLE tableA (colA INTEGER, ...)


CREATE PROCEDURE "SCHEMA"."PURGE_PROC"
(IN batchSize INTEGER)
LANGUAGE SQL
SPECIFIC SQL140207163731500
BEGIN

   DECLARE tempID             INTEGER;
   DECLARE eof_bool           INTEGER DEFAULT 0;
   DECLARE sqlString          VARCHAR(1000);
   DECLARE sqlStmt            STATEMENT;
   DECLARE myCurs             CURSOR WITH HOLD FOR sqlStmt;
   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET eof_bool = 1;

   SET sqlString = 'select colA from TableA';
   PREPARE sqlStmt FROM sqlString;

   OPEN myCurs;
   FETCH myCurs INTO tempID;
   WHILE (eof_bool = 0) DO
        DELETE FROM TableA where colA = tempID;
        FETCH myCurs INTO tempID;
   END WHILE;

   COMMIT;
   CLOSE myCurs;

END

注意:在我的真实场景中:

  • 我没有删除表中的所有记录,只是根据一些额外的标准删除了某些记录;和
  • 我计划在WHILE循环的每N#次迭代(比如500或1000)中执行COMMIT,而不是像上面那样整个混乱;和
  • 我计划删除多个表,而不仅仅是这个表;

但是,为了简化,我测试了上面的代码,我看到的是DELETE似乎是逐个提交的。我基于以下测试:

  • 我用(例如50k)记录预加载表格;
  • 然后运行purge storedProc,需要大约60秒才能运行;
  • 在这段时间内,从另一个SQL客户端,我不断“SELECT COUNT(*)FROM tableA”,并看到计数逐渐减少。

如果所有DELETE都立刻被提交,我希望看到记录计数(*)在~60秒结束时仅从0下降到0。这就是我在为Oracle或SQLServer编写的类似SP中看到的。

这是Win2003上的DB2 v9.5。

我缺少什么想法?

2 个答案:

答案 0 :(得分:0)

您缺少不同数据库引擎之间的并发控制实现的差异。在Oracle数据库中,另一个会话将看到在其事务开始之前已提交的数据,也就是说,在第一个会话提交之前,它不会看到任何删除。

在DB2中,根据服务器配置参数(例如DB2_SKIPDELETED)和/或第二个会话隔离级别(例如未提交的读取),它实际上可以看到(或不看到)受到正在进行的事务影响的数据。

如果您的业务逻辑需要不同的事务隔离,请与您的DBA联系。

答案 1 :(得分:0)

应该指出你正在删除“光标之外”

使用光标删除的正确方法是使用“定位删除”

DELETE FROM tableA WHERE CURRENT OF myCurs;

以上内容删除刚刚获取的行。