Insert SQL Command with dynamic Username and rowtypes
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;
Я получаю следующее сообщение об ошибке:
Please-00306 wrong number or types of arguments in call
With the following syntax
stmt:='insert into ' || nachdb || ' ."Kunden" values vKunden ';
execute immediate stmt ;
Я получаю следующее сообщение:
ORA-03001: unimplemented feature
2 ответа
Кажется, ты не можешь этого сделать. В первой попытке вы пытаетесь объединить тип записи PL/SQL (из %rowtype
) на строку; если бы он позволил вам тогда, что бы он поместил, свое внутреннее представление записи? Для того чтобы он был действительным оператором вставки, он должен был бы перевести его в список значений из записи, как (col1, col2, ...)
, который просит довольно много об этом.
Во второй версии, с ORA-03001, я думаю, что это потому, что он интерпретирует vKunden
в качестве идентификатора объекта; переменная записи в блоке PL/SQL не входит в область действия оператора SQL.
Предположительно, вы пытались использовать для этого переменную связывания и обнаружили, что это невозможно, поскольку переменные связывания должны быть типов SQL (PLS-00457).
Вы могли бы возможно использовать DBMS_SQL
пройти через %rowtype
переменная и создать свой собственный values
предложение, основанное на столбцах / полях, которые оно содержит, но это кажется болезненным.
Предположительно, хотя различные версии "Kunden"
(идентификаторы объектов в кавычках? не кажется ли вам, что работать с ними очень больно?) все идентичны, в противном случае %rowtype
вы используете, чтобы объявить vKunden
в любом случае не будет применяться для вставки, и поэтому вы знаете все имена столбцов. Вы должны будете связать каждое значение столбца индивидуально:
stmt:='insert into ' || nachdb || ' ."Kunden" ("KndNr", "Col2", ...)'
|| ' values (:1, :2, ...)';
execute immediate stmt using vKunden."KndNR", vKunden."Col2", ...;
Хотя еще проще было бы:
stmt:='insert into ' || nachdb || ' ."Kunden"'
|| ' select * from "Kunden" where "KndNr"=55';
execute immediate stmt;
... который обходит vKunden
и %rowtype
выдать в целом. Вы делаете этот выбор несколько раз, но это не может быть значительным количеством накладных расходов
Просто чтобы добавить, почему это не сработает: 03001 потому что у вас нет скобок () вокруг значений. Даже с скобками это не сработает, потому что vKunden имеет%rowtype, поэтому вы не можете передать это в динамический sql (pls-00457). Вы можете проверить это, используя: execute немедленный 'select:1 from dual' using vKunden;