Открыть сервис

EXECUTE IMMEDIATE

EXECUTE IMMEDIATE — это оператор языка SQL, входящий в состав расширения PL/SQL (Procedural Language/Structured Query Language) в системах управления базами данных (СУБД) Oracle Database, а также в некоторых других СУБД, поддерживающих динамический SQL. Он предназначен для выполнения строковых выражений, содержащих команды SQL или блоки PL/SQL, которые формируются и интерпретируются во время выполнения программы (динамически), а не на этапе компиляции.

Назначение и область применения

Основное назначение оператора EXECUTE IMMEDIATE — обеспечение возможности построения и выполнения SQL-запросов, структура которых неизвестна на момент написания кода. В отличие от статического SQL, где текст запроса жёстко задан в исходном коде, динамический SQL позволяет изменять таблицы, столбцы, условия и другие элементы запроса в зависимости от входных данных, параметров окружения или логики приложения.

Оператор используется в следующих типичных сценариях:

  • выполнение DDL-команд (Data Definition Language), таких как CREATE, ALTER, DROP, TRUNCATE, которые не поддерживаются в статическом PL/SQL;
  • выполнение DML-команд (Data Manipulation Language) с изменяемыми именами таблиц или столбцов;
  • выполнение блоков PL/SQL, сформированных динамически;
  • обработка запросов, параметры которых (например, значения в WHERE) задаются во время выполнения;
  • построение запросов на основе метаданных словаря данных.

Синтаксис

Общий синтаксис оператора EXECUTE IMMEDIATE в Oracle Database выглядит следующим образом:

``sql EXECUTE IMMEDIATE 'строка_с_sql_или_plsql' [INTO {переменная [, переменная]... | запись}] [USING [IN | OUT | IN OUT] параметр [, параметр]...] [RETURNING {переменная [, переменная]... | запись} INTO {переменная [, переменная]... | запись}]; ``

  • строка_с_sql_или_plsql — обязательный строковый литерал или переменная типа VARCHAR2, содержащая корректную команду SQL или блок PL/SQL.
  • INTO — необязательное предложение, используемое для захвата результатов выполнения запроса SELECT, возвращающего одну строку.
  • USING — необязательное предложение для передачи входных параметров в динамический запрос или приёма выходных значений (для OUT и IN OUT). Параметры могут быть любого типа данных SQL.
  • RETURNING ... INTO — необязательное предложение, используемое с DML-командами (INSERT, UPDATE, DELETE), которые содержат предложение RETURNING, для захвата возвращаемых значений (например, сгенерированных идентификаторов).

Принцип работы

При вызове EXECUTE IMMEDIATE происходит следующий процесс:

  1. Парсинг — строка с SQL-командой разбирается синтаксическим анализатором СУБД. Если строка содержит синтаксическую ошибку, возникает исключение.
  2. Подстановка параметров — если указано предложение USING, значения переменных подставляются в места, обозначенные плейсхолдерами (обычно двоеточие с именем, например :x). Плейсхолдеры могут использоваться только для значений, но не для идентификаторов (имён таблиц, столбцов).
  3. Выполнение — команда выполняется. Для DDL-команд выполнение происходит немедленно, для DML — в рамках текущей транзакции.
  4. Возврат результатов — если указано предложение INTO, результат запроса SELECT (одна строка) помещается в указанные переменные. Если указано RETURNING INTO, возвращаемые значения DML-команды помещаются в переменные.

Особенности и ограничения

  • Отсутствие проверки на этапе компиляции — ошибки в динамическом SQL (например, обращение к несуществующей таблице) проявляются только во время выполнения, что может привести к исключениям.
  • Производительность — каждый вызов EXECUTE IMMEDIATE требует полного цикла парсинга, что делает его более медленным по сравнению со статическим SQL, особенно при многократном выполнении одной и той же команды. Для повышения производительности в Oracle рекомендуется использовать статический SQL или динамический SQL с привязкой переменных (USING), что позволяет повторно использовать курсоры.
  • Уязвимость к SQL-инъекциям — конкатенация строк для построения динамического запроса без экранирования может привести к внедрению вредоносного кода. Для предотвращения необходимо использовать механизм плейсхолдеров и привязку переменных через USING.
  • Ограничение на длину строки — строка с SQL-командой не должна превышать максимальную длину, поддерживаемую типом VARCHAR2 (в Oracle — до 32767 байт в PL/SQL).
  • Не поддерживает запросы, возвращающие несколько строк — для таких запросов необходимо использовать динамический курсор (REF CURSOR).

Примеры использования

Выполнение DDL-команды

``sql BEGIN EXECUTE IMMEDIATE 'CREATE TABLE temp_table (id NUMBER, name VARCHAR2(100))'; END; ``

Динамический DML с параметрами

``sql DECLARE v_table_name VARCHAR2(30) := 'employees'; v_employee_id NUMBER := 101; v_salary NUMBER; BEGIN EXECUTE IMMEDIATE 'SELECT salary FROM ' || v_table_name || ' WHERE employee_id = :id' INTO v_salary USING v_employee_id; DBMS_OUTPUT.PUT_LINE('Salary: ' || v_salary); END; ``

Динамический блок PL/SQL

``sql DECLARE v_sql VARCHAR2(200); v_result NUMBER; BEGIN v_sql := 'BEGIN :res := 10 * 5; END;'; EXECUTE IMMEDIATE v_sql USING OUT v_result; DBMS_OUTPUT.PUT_LINE('Result: ' || v_result); END; ``

Альтернативы и сравнение

В Oracle Database существуют и другие механизмы для работы с динамическим SQL:

  • DBMS_SQL — более низкоуровневый пакет, предоставляющий полный контроль над процессом парсинга, выполнения и получения результатов. В отличие от EXECUTE IMMEDIATE, он позволяет выполнять запросы, возвращающие несколько строк, и обрабатывать динамические курсоры с неизвестным количеством столбцов. Однако он требует больше кода и сложнее в использовании.
  • REF CURSOR — используется для выполнения динамических запросов SELECT, возвращающих набор строк, с возможностью последующей выборки.

EXECUTE IMMEDIATE является более простым и удобным инструментом для большинства задач динамического SQL, особенно для DDL и однострочных DML-запросов.

Поддержка в других СУБД

Хотя EXECUTE IMMEDIATE является частью стандарта PL/SQL, аналогичные конструкции существуют и в других системах:

  • В СУБД IBM Db2 для языка SQL PL используется оператор EXECUTE IMMEDIATE с аналогичным синтаксисом.
  • В PostgreSQL для динамического выполнения SQL в PL/pgSQL применяется команда EXECUTE, которая не требует ключевого слова IMMEDIATE, но выполняет ту же функцию.
  • В Microsoft SQL Server для динамического SQL используется системная хранимая процедура sp_executesql или функция EXECUTE.

Источники

  • Oracle Database SQL Language Reference, 19c
  • Oracle Database PL/SQL Language Reference, 19c
  • Feuerstein S., Pribyl B. «Oracle PL/SQL Programming», 6th Edition, O'Reilly Media, 2014
  • Документация IBM Db2 SQL PL
  • Документация PostgreSQL PL/pgSQL

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →