A простое, но статичное решение предполагает наличие известного списка переменных связывания и их типов данных, и динамические запросы могут использовать только подмножество этих переменных связывания.
Вот пример для пяти VARCHAR
переменных связывания. Вы генерируете этот блок PL / SQL:
DECLARE
L_VC1 VARCHAR2(4000) := :VC1;
L_VC2 VARCHAR2(4000) := :VC2;
L_VC3 VARCHAR2(4000) := :VC3;
L_VC4 VARCHAR2(4000) := :VC4;
L_VC5 VARCHAR2(4000) := :VC5;
BEGIN
-- here an statement using L_VC1 up to L_VC5
-- eg
INSERT INTO test (vc1,vc2,vc3) values (L_VC1, L_VC2, L_VC3);
END;
и выполняет его, передавая полный список значений (некоторые из них остались NULL
).
EXECUTE IMMEDIATE my_generated_block USING vc1, vc2, vc3, vc4, vc5;
Приятной особенностью является то, что динамический SQL может использовать одну переменную связывания несколько раз без необходимости расширения параметров USING
.
Это, конечно, должно сохраняться, если появляется новая переменная.
Что является альтернативой?
По моему мнению, чтобы быть действительно динамичным в списке переменных связывания, вы не можете решить это с помощью EXECUTE IMMEDIATE
, и вы должны сделать шаг вниз к DBMS_SQL
.
Вот идея, без подробностей, как реализовать это в PL / SQL:
DECLARE
cursor_name INTEGER;
rows_processed INTEGER;
BEGIN
cursor_name := dbms_sql.open_cursor;
DBMS_SQL.PARSE(cursor_name, 'INSERT INTO test (vc1,vc2,vc3) values (:vc1, :vc2, :vc3)',
DBMS_SQL.NATIVE);
-- call in a loop for each BV
DBMS_SQL.BIND_VARIABLE(cursor_name, ':vc1', 'x');
DBMS_SQL.BIND_VARIABLE(cursor_name, ':vc2', 'y');
DBMS_SQL.BIND_VARIABLE(cursor_name, ':vc3', 'z');
---
rows_processed := DBMS_SQL.EXECUTE(cursor_name);
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
/
Вам придется вызывать DBMS_SQL.BIND_VARIABLE
в цикле для каждого имени переменной связывания и значения.
Обратите внимание, что я полностью игнорирую тип данных переменных связывания, который также следует учитывать и, вероятно, сделает решение более сложным, но его можно решить.
Какое решение более целесообразно?
Если ваш реляционный дизайн базы данных действительно ключ - значение (т.е. вы можете вводить новые переменные связывания без DDL
), вам придется следовать второму варианту. В противном случае, то есть, если для получения новой переменной связывания требуется изменение структуры таблицы, и если частота изменений низкая, я бы предпочел первый вариант.