Reputation: 25
I'd like to generate a dynamic Insert statement with different Username and data from a rowtype
My snippet
create or replace procedure test()
is
TYPE cv_typ is REF CURSOR;
cv cv_typ;
stmt varchar(2000);
zieldb varchar(20);
vKunden "Kunden"%rowtype;
BEGIN
execute immediate 'select * from "Kunden" where "KndNr"=55 ' into vKunden;
stmt:='select kc.zieldb from test.kunden_copy kc, test.transrel vd
where kc.zieldb=vd.dbname and kc.status=1 ';
OPEN cv FOR stmt;
LOOP
FETCH cv into nachdb;
EXIT WHEN cv%NOTFOUND;
...
...
stmt:='insert into ' || nachdb || ' ."Kunden" values ' || vKunden;
execute immediate stmt ;
...
...
END LOOP;
END;
I get the following error message:
Please-00306 wrong number or types of arguments in call
With the following syntax
stmt:='insert into ' || nachdb || ' ."Kunden" values vKunden ';
execute immediate stmt ;
I get the following message:
ORA-03001: unimplemented feature
Upvotes: 0
Views: 1256
Reputation: 1
Just to add why it won't work: The 03001 is because you don't have brackets () around the values. Even with brackets it won't work, because vKunden is of %rowtype, so you cannot pass this into a dynamic sql (pls-00457). You can check this by using: execute immediate 'select :1 from dual' using vKunden;
Upvotes: 0
Reputation: 191435
It seems you can't do that. In your first attempt you're trying to concatenate a PL/SQL record type (from the %rowtype
) onto a string; if it let you then what would it put, its internal representation of the the record? For it to be a valid insert statement it would have to translate it into a list of values from the record, as (col1, col2, ...)
, which is asking quite a lot of it.
In your second version, with the ORA-03001, I think that's because it's interpreting vKunden
as an object identifier; the record variable in the PL/SQL block isn't in scope in the SQL statement.
Presumably you've tried using a bind variable for this, and discovered that you can't, because bind variables have to be SQL types (PLS-00457).
You could perhaps use DBMS_SQL
to step through the %rowtype
variable and build up your own values
clause based on the columns/fields it contains, but that seems painful.
Presumably though the various versions of "Kunden"
(quoted object identifiers? don't you find that very painful to work with?) are all identical, otherwise the %rowtype
you're using to declare vKunden
wouldn't apply for the insert anyway, and so you know all the column names. You would have to bind each column value individually:
stmt:='insert into ' || nachdb || ' ."Kunden" ("KndNr", "Col2", ...)'
|| ' values (:1, :2, ...)';
execute immediate stmt using vKunden."KndNR", vKunden."Col2", ...;
Although even simpler would be:
stmt:='insert into ' || nachdb || ' ."Kunden"'
|| ' select * from "Kunden" where "KndNr"=55';
execute immediate stmt;
... which bypasses vKunden
and the %rowtype
issue altogether. You're doing that select multiple times, but that's might not be a significant amount of overhead
Upvotes: 1