Reputation: 1064
I have the problem of creating a backup for a table by creating a series of insert statements.
The input is the table name and each table can have a different number of columns. It is assumed that data types can be varchar2, number, or date only
so I have this line of code:
execute immediate fetchStmt;
where fetchStmt can be:
fetch tableColCursor into valuesArray(1), valuesArray(2), ..., valuesArray(n)
This just fetches each row from the cursor and puts it into a varray, the statements itself works if it is not in an execute immediate statement.
I do know that an execute immediate can only process SQL queries or PL/SQL blocks. The problems is how would I be able to make this work or what can be a similar solution to the problem?
Note that it is not known during compile time the table and its columns and their data types
Upvotes: 1
Views: 707
Reputation: 67742
EXECUTE IMMEDIATE
can only process full statements, i-e: SQL statements or PLSQL blocks (with [DECLARE]..BEGIN..END
).
Furthermore, a block executed this way won't see any variables from the calling block (they don't share the same scope), for instance this won't work:
DECLARE
l NUMBER := 1;
k NUMBER := 0;
BEGIN
EXECUTE IMMEDIATE 'BEGIN l := k; END;';
END;
The above code will produce an error because l
and k
are not defined in the sub-block. Instead you would need to use input/output variables:
DECLARE
l NUMBER := 1;
k NUMBER := 0;
BEGIN
EXECUTE IMMEDIATE 'BEGIN :P1 := :P2; END;' USING OUT l, k;
dbms_output.put_line(l); -- return 0
END;
In your case you don't know the number of variables so you won't be able to use EXECUTE IMMEDIATE
. You could use DBMS_SQL
but I think there are simpler methods: you could find already working code (it exists within Oracle APEX for instance), or you could program it yourself by running a SELECT that would produce the necessary INSERT string. For this method you would have to generate the SQL statement dynamically (dependent upon the table columns). The statement would look like this (for a table TEST(a,b,c)
where all columns are integer [needs adapting for other datatypes]):
SELECT 'INSERT INTO test(a,b,c) VALUES ('||a||', '||b||', '||c||');'
FROM test
Upvotes: 2