Search code examples
sqlplsqldb2cursorplsqldeveloper

IBM plsql - cursor


I am new with PLSQL (IDM db2) and I am trying to create a procedure to find and delete some admin_tasks if they exist.

Explanation: By running the bellow query1, I can find out the list of tasks in the scheduler:

SELECT * FROM SYSTOOLS.ADMIN_TASK_LIST; 

To delete the task, I can run this query2:

call sysproc.admin_task_remove('TASK_NAME', null);

So I want to create a procedure to delete all tasks with the pattern "My_Task_*". This should delete all the tasks with that pattern and leave the other existent tasks intact. The procedure should handle cases where the admin_tasks doesn't exist, or no admin_tasks were ever created, and should run without throwing any errors.

I have researched and found out that this can be made using cursors.

Can you help me to implement this?

EDIT: I managed to find this solution:

BEGIN
  FOR v1 AS c1 CURSOR FOR
    SELECT NAME 
    FROM SYSTOOLS.ADMIN_TASK_LIST
    WHERE NAME LIKE 'My\_task\_%' ESCAPE '\'
   DO
    call sysproc.admin_task_remove(NAME, null);
  END FOR;
END

This seems to work except if the SYSTOOLS.ADMIN_TASK_LIST was not yet defined.

If it's not defined than I get this error when I run the query: If it is not defined I get this error : [Code: -204, SQL State: 42704]

"SYSTOOLS.ADMIN_TASK_LIST" is an undefined name.. SQLCODE=-204, SQLSTATE=42704, DRIVER=4.25.1301

So how can I bypass this error? DOing something like first checking if SYSTOOLS.ADMIN_TASK_LIST is defined, if its defined to the above query if not do nothing.


Solution

  • Presuming that your client tool uses '@' as a statement delimiter.

    BEGIN
      FOR L1 AS 
        SELECT NAME 
        FROM SYSTOOLS.ADMIN_TASK_LIST
        WHERE NAME LIKE 'My\_task\_%' ESCAPE '\'
      DO
        CALL ADMIN_TASK_REMOVE (L1.NAME, NULL);
      END FOR;
    END
    

    Update:
    With error handling for non-existing table. The error handler just "eats" the error on non-existing table use. You must use dynamic sql for that.

    BEGIN
      DECLARE SQLSTATE CHAR (5);
      DECLARE L_NAME VARCHAR (128);
      DECLARE C1 CURSOR FOR S1; 
      DECLARE EXIT HANDLER FOR SQLSTATE '42704' BEGIN END;
      PREPARE S1 FROM 
        '
        SELECT NAME 
        FROM SYSTOOLS.ADMIN_TASK_LIST
        WHERE NAME LIKE ''My\_task\_%'' ESCAPE ''\''
        ';
      OPEN C1;
      L1:
      LOOP
        FETCH C1 INTO L_NAME;
        IF SQLSTATE = '02000' THEN LEAVE L1; END IF;
        CALL ADMIN_TASK_REMOVE (L_NAME, NULL);
      END LOOP L1;
      CLOSE C1;
    END