سؤال

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

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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;

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top