How to duplicate rows with a column change for a list of tables?

Viewed 90

Given the following example:

BEGIN
    FOR r IN (
        SELECT * FROM table_one WHERE change_id = 0
    ) LOOP
        r.change_id := -1;
        INSERT INTO table_one VALUES r;

    END LOOP;
END;

This inserts new rows to table_one with the exact same content, except the intended change on column change_id to the value -1. I don't have to specify the columns inside of the script as I have to in an INSERT INTO table_one (change_id, ...) SELECT -1, ... FROM table_one WHERE change_id=0;

It works perfectly fine. But how to modify this script to work with a list of tables? The internal structure of those tables are different, but all of them have the necessary column change_id.

Of course the easiest solution would be to copy and paste this snippet x-times and replace the fix table name inside. But is there an option to work with a list of tables in an array?

My approach was like this:

DECLARE
    TYPE tablenamearray IS VARRAY(30) OF VARCHAR2(30);
    tablenames tablenamearray;

BEGIN
    tablenames := tablenamearray('TABLE_ONE', 'TABLE_TWO', 'TABLE_THREE'); -- up to table 30...
  
    FOR i IN tablenames.first..tablenames.last LOOP 

        /* Found no option to use tablenames(i) here with dynamic SQL */
        
    END LOOP;

END;

Note: There is no technical primary key like an id with a sequence behind. The primary key is build by three columns incl. the change_id column.

1 Answers

You cannot create a SQL statement where the statement is not known at parse time. So, you cannot have a variable as a table name. What you're looking for is Dynamic SQL, which is a fairly complicated topic, but basically you're going to wind up building a SQL statement with DBMS_SQL or running a statement as a string with EXECUTE IMMEDIATE.

Related