stored-proceduresplsqldb2sql-pl

Convert Procedure from Oracle to DB2, Error when try to update table on runtime


Hello DB2 Experts I need your assistance in converting below Procedure to something more dynamic. We have to update multiple sequences with max of id column for each table.

CREATE PROCEDURE mySchema.UPDATE_SEQUENCE ( )
 DYNAMIC RESULT SETS 1
 MODIFIES SQL DATA
----------------------------------------------------------------------
-- SQL Stored Procedure
----------------------------------------------------------------------
P1: BEGIN
 DECLARE counter BIGINT;
 DECLARE q VARCHAR(500);
set (counter) = (select max(N_PRI_KEY) from mySchema.myTable);
set q = 'alter sequence mySchema.mySequence RESTART WITH ' || counter;
 EXECUTE IMMEDIATE q;

END P1
@

This is what I have written from the above code: Here I want N_PRI_KEY to be dynamic and mySchema.myTable to be updated on run time with the values from the table.

CREATE OR REPLACE PROCEDURE getText ()
LANGUAGE SQL
DYNAMIC RESULT SETS 1
  BEGIN
  DECLARE maxval  INTEGER DEFAULT 0;

  CALL DBMS_OUTPUT.PUT( 'a' );

  FOR vrows AS 
      SELECT NAME, SEQUENCENAME, TBNAME FROM MAXSEQUENCE WHERE SEQUENCENAME='ASSETSEQ'
    DO 

      SELECT MAX(vrows.NAME) INTO maxval FROM vrow.TBNAME; -- This is where I am getting error.

    EXECUTE IMMEDIATE 'ALTER SEQUENCE '||vrows.SEQUENCENAME||' RESTART WITH '|| maxval;

  END FOR;      
END@

This is the error that I am getting when I try to create the Procedure.

DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL0204N  "VROW.TBNAME" is an undefined name.  LINE NUMBER=18.  SQLSTATE=42704

When I run this line it works and inserts the max value in the TEMPOUTPUT table.

execute immediate  'INSERT INTO TEMPOUTPUT VALUES (select max('||vrow.NAME||') from '||vrow.TBNAME||')';

I have tried doing this but it did not work.

execute immediate  'ALTER SEQUENCE '||SEQUENCENAME||' RESTART WITH select max('||vrow.NAME||') from '||vrow.TBNAME;

Just for Reference - This is a procedure which is written in Oralce which is doing something similar.


declare
    maxval int;
    seqval int;
  begin
  for i in ( select ucc.column_name, s.sequence_name, uc.table_name
             from   user_cons_columns ucc,
                    user_constraints uc,
                    user_sequences s
             where  uc.constraint_name = ucc.constraint_name
             and    uc.constraint_type = 'P'
             and    ucc.position = 1
             and    s.sequence_name = 'SEQ_'||uc.table_name
           )
  loop
    execute immediate  'select max('||i.column_name||') from '||i.table_name into maxval;
    execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;

    dbms_output.put_line(maxval||','||seqval);

     if maxval > seqval then
        execute immediate  'alter sequence '||i.sequence_name||' increment by '|| ( maxval - seqval );
        execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
        execute immediate  'alter sequence '||i.sequence_name||' increment by 1';
        execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
        dbms_output.put_line(maxval||','||seqval);
     end if;
  end loop;
  end;

Solution

  • Try the following instead of the row with SELECT MAX(...) where you get the error:

    PREPARE S1 FROM 'SET ? = (SELECT MAX(' || vrows.NAME || ') FROM ' || vrows.TBNAME || ')';
    EXECUTE S1 INTO maxval;