Почему я не могу использовать переменные привязки в операторах DDL/SCL в динамическом SQL?
Я пытаюсь выполнить команду SQL в динамическом SQL с переменными bind:
-- this procedure is a part of PL/SQL package Test_Pkg
PROCEDURE Set_Nls_Calendar(calendar_ IN VARCHAR2)
IS
BEGIN
EXECUTE IMMEDIATE
'ALTER SESSION
SET NLS_CALENDAR = :cal'
USING IN calendar_;
END Set_Nls_Calendar;
затем на стороне клиента, я пытаюсь вызвать процедуру:
Test_Pkg.Set_Nls_Calendar('Thai Buddha');
но это get's me ORA-02248: invalid option for ALTER SESSION
.
и мой вопрос: почему я не могу использовать переменные привязки в операторах DDL/SCL в динамическом SQL?
1 ответов
переменные привязки не разрешены в инструкциях DDL. Таким образом, следующие утверждения вызовут ошибки:
-
Пример #1: DDL statement. Вызовет ORA-01027: привязка переменных не допускается для операций определения данных
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )' USING 42;
-
Пример #2: DDL statement. Вызовет ORA-00904:: неверно идентификатор
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( :col_name NUMBER )' USING var_col_name;
-
Пример #3: SCL statement. Вызовет ORA-02248: недопустимый параметр для ALTER SESSION
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = :cal' USING var_calendar_option;
чтобы понять, почему это происходит, нам нужно посмотреть на как обрабатываются динамические операторы SQL.
обычно прикладная программа запрашивает у пользователя текст SQL оператор и значения переменных хоста, используемые в операторе. Затем Oracle анализирует инструкцию SQL. То есть Oracle проверяет инструкцию SQL, чтобы убедиться, что она следует правилам синтаксиса и относится к допустимым объектам базы данных. Синтаксический анализ также включает проверку прав доступа к базе данных1, резервирования необходимых ресурсов и поиск оптимального пути доступа.
1выделено ответчик!--62-->
обратите внимание, что шаг разбора происходит до привязка любых переменных к динамическому оператору. Если вы изучите приведенные выше четыре примера, вы поймете, что синтаксический анализатор не может гарантировать синтаксическую валидность этих динамических операторов SQL, не зная значений для переменных привязки.
-
Пример 1: парсер не может сказать, будет ли значение привязки допустимым. Что, если вместо
USING 42
, программиста, писалUSING 'forty-two'
? -
Пример #2: парсер не может сказать, если
:col_name
будет допустимым именем столбца. Что делать, если имя связанного столбца было'identifier_that_well_exceeds_thirty_character_identifier_limit'
? -
Пример #3: значения
NLS_CALENDAR
встроенные константы (для данной версии Oracle?). Парсер не может сказать, будет ли связанная переменная иметь допустимое значение.
Итак, ответ таков:вы не можете привязать элементы схемы, такие как имена таблиц, имена столбцов в динамическом SQL. Также вы не можете связать встроенные константы.
решение
единственный способ динамически ссылаться на элементы/константы схемы-использовать конкатенацию строк в динамических инструкциях SQL.
-
Пример 1:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
-
пример #2:
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
-
Пример #3:
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';