Question

I've only been writing DB2 procedures for a few days, but trying to do a "batch delete" on a given table. My expected logic is:

  • to open a cursor
  • walk through it until EOF
  • issue a DELETE on each iteration

For sake of simplifying this question, assume I only want to issue a single COMMIT (of all DELETEs), after the WHILE loop is completed (ie. once cursor reaches EOF). So given the code sample below:

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

Note: In my real scenario:

  • I am not deleting all records from the table, just certain ones based on some additional criteria; and
  • I plan to perform a COMMIT every N# iterations of the WHILE loop (say 500 or 1000), not the entire mess like above; and
  • I plan to DELETE against multiple tables, not just this one;

But again, to simplify, I tested the above code, and what I'm seeing is that the DELETEs seem to be getting committed 1-by-1. I base this on the following test:

  • I pre-load the table with (say 50k) records;
  • then run the purge storedProc which takes ~60 secs to run;
  • during this time, from another sql client, I continuously "SELECT COUNT(*) FROM tableA" and see count reducing incrementally.

If all DELETEs were committed at once, I would expect to see the record count(*) only drop from to 0 at the end of the ~60 seconds. That is what I see with comparable SPs written for Oracle or SQLServer.

This is DB2 v9.5 on Win2003.

Any ideas what I'm missing?

Was it helpful?

Solution

You are missing the difference in concurrency control implementation between the different database engines. In an Oracle database another session would see data that have been committed prior to the beginning of its transaction, that is, it would not see any deletes until the first session commits.

In DB2, depending on the server configuration parameters (e.g. DB2_SKIPDELETED) and/or the second session isolation level (e.g. uncommitted read) it can in fact see (or not see) data affected by in-flight transactions.

If your business logic requires different transaction isolation, speak with your DBA.

OTHER TIPS

It should be pointed out that you're deleting "outside of the cursor"

The right way to delete using the cursor would be using a "positioned delete"

DELETE FROM tableA WHERE CURRENT OF myCurs;

The above deletes the row just fetched.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top