Инструменты пользователя

Инструменты сайта


Боковая панель

execute_statement



EXECUTE STATEMENT

Оператор EXECUTE STATEMENT имеет две редакции. Впервые оператор EXECUTE STATEMENT появился в версии 1.5.3, в последствии в альфа релизе версии 2.5 синтаксис оператора был изменен с целью поддержки Cross-Database и параметризированных запросов таким образом, что синтаксис версии 1.5.3 является частным случаем синтаксиса версии 2.5.

Версии сервера

Первая редакция синтаксиса оператора

0.9 1.0 1.5.3 1.5.4 1.5.5 2.0 2.0.3 2.0.4 2.1 2.5 3.0
- - Да Да Да Да Да Да Да Частный случай Частный случай

Вторая редакция синтаксиса оператора

0.9 1.0 1.5.3 1.5.4 1.5.5 2.0 2.0.3 2.0.4 2.1 2.5 3.0
- - - - - - - - - Да Да

Доступно в

Формат

Первая редакция синтаксиса оператора

 
Параметр Значение
<sql_statement_string> Строка, содержащая правильный SQL-запрос, или это может быть
<SQL_STMT_VARIABLE> переменная, значению которой присваивается правильный SQL-запрос
<VARIABLE_1> Переменная или переменные, перечисленные через запятую, куда необходимо вернуть значения в случае селективного запроса.
<sql_operator> SQL-оператор, который необходимо выполнять в случае циклического выполнения селективного запроса. Оператор может быть как простой, так и составной - состоящий из нескольких операторов, заключенных в операторные скобки BEGIN…END.

Вторая редакция синтаксиса оператора

 
Параметр Значение
<sql_statement_string> Строка, содержащая правильный SQL-запрос, или это может быть
<SQL_STMT_VARIABLE> переменная, значению которой присваивается правильный SQL-запрос. В отличие от первой редакции синтаксиса оператора, во второй редакции синтаксиса SQL-запрос может содержать параметры.
<input_parameters> Присваивание значений параметрам в случае параметризированного SQL-запроса.
<connection_string> Строка подключения к базе данных в формате, используемом в API-функции сервера isc_attach_database().
AUTONOMOUS или COMMON Указывает, выполнять оператор в текущей или автономной транзакции. Если не задан явно, выполнение оператора происходит в текущей транзакции.
<user_name> Имя пользователя, от имени которого будет выполнен SQL-оператор. В качестве значения можно передавать контекстную переменную CURRENT_USER. Если параметр не задан явно, то используется текущий пользователь.
<password> Строка или переменная, содержащая пароль пользователя, от имени которого будет выполнен SQL-оператор, для подключения к базе данных. Если не указан параметр <user_name> или значение параметра <user_name> равно CURRENT_USER, то указание пароля можно пропустить при выполнении оператора.
<VARIABLE_1> Переменная или переменные, перечисленные через запятую, куда необходимо вернуть значения в случае селективного запроса.
<sql_operator> SQL-оператор, который необходимо выполнять в случае циклического выполнения селективного запроса. Оператор может быть как простой, так и составной - состоящий из нескольких операторов, заключенных в операторные скобки BEGIN…END.

Описание

Описание к первой редакции

Описание к первой редакции синтаксиса оператора относится и ко второй в виду вертикальной совместимости версий сервера.

Оператор позволяет выполнить правильный SQL-запрос в PSQL-блоках, триггерах и процедурах.

:!: SQL-запрос должен быть тривиальным или атомарным. То есть Вы не можете выполнить несколько SQL-запросов, перечислив их через разделитель в рамках одного оператора EXECUTE STATEMENT. Для того, чтобы выполнить несколько SQL-запросов, Вам необходимо вызвать EXECUTE STATEMENT для каждого из них.

SQL-запрос может быть:

:!: В первой редакции синтаксиса оператора EXECUTE STATEMENT SQL-запрос не может содержать никаких параметров !

:!: EXECUTE STATEMENT потенциально опасен:

  1. Не делается никакой проверки запроса на выполнения. Так же не может быть проверен результат запроса и успешность его выполнения.
  2. Не может быть выполнена проверка зависимостей в случае выполнения DML-оператора для гарантии того, что объекты, указанные в строке SQL операторов не удаляются из базы данных или не изменяются таким образом, который нарушит функционирование вашей задачи. Например, допускается выполнение команды DROP TABLE для таблицы, которая используется в откомпилированных процедурах или триггерах, что повлечет за собой сбой их работы.
  3. В основном операции с EXECUTE STATEMENT более медленые так как не делается подготовка(prepared) запроса и, соответствено, подготовка происходит каждый раз при выполнении.

Это не означает что вы не должны использовать эту возможность, но используйте её только в том случае если другие варианты невозможны.

:!: Для облегчения поиска багов в коде, или для их исключения, возвращаемые параметры жестко проверяются на соответствие объявленным типам данных. Это помогает избежать ошибок, когда приведение типов может как вызвать ошибку, так и не вызвать. Например, строка '1234' может быть сконвертирована в целое число 1234, а строка 'abc' в целое число сконвертирована быть не может.

:!: В первой редакции синтаксиса оператора EXECUTE STATEMENT если PSQL-блок, хранимая процедура или триггер, вызывающий EXECUTE STATEMENT, имеет особые права на обьект базы данных, то SQL-запрос выполняемый в EXECUTE STATEMENT не будет иметь таких прав, а только права пользователя под которым выполняется эта процедура. (прим.переводчика: во второй редакции синтаксиса оператора данное ограничение снято введением раздела WITH CALLER PRIVILEGES)

Описание ко второй редакции

В описании ко второй редакции синтаксиса оператора следует учитывать замечания к первой редакции в виду вертикальной совместимости версий сервера.

:!: Порядок следования следующих разделов оператора EXECUTE STATEMENT

  .......
      [ON EXTERNAL [DATA SOURCE] <connection_string>]
      [WITH { AUTONOMOUS | COMMON } TRANSACTION]
      [AS USER <user_name> [PASSWORD <password>] ]
      [WITH CALLER PRIVILEGES]
  .......

не является жестким, то есть разделы могут перечисляться в произвольном порядке. При этом повторное использование разделов оператора в рамках одного оператора EXECUTE STATEMENT запрещено!

:!: Во второй редакции синтаксиса оператора разрешено использовать параметризированные запросы при соблюдении следующих условий:

1)Если вы желаете использовать параметризированный запрос, то Вы обязаны заключить строку или переменную, содержащую текст Вашего параметризированного запроса в круглые скобки. Например:

  EXECUTE STATEMENT (:P_SQL_STMT) (P1 := 'abc', P2 := :MY_VARIABLE);

2) В параметризированных запросах поддерживаются оба типа параметров: именованные и безымянные. Например:

EXECUTE BLOCK AS
  DECLARE S VARCHAR(255);
BEGIN
  -- Именованные параметры запроса
  S = 'INSERT INTO TTT VALUES (:A, :B, :A)'; 
  EXECUTE STATEMENT (:S) (A := CURRENT_TRANSACTION, B := CURRENT_CONNECTION)
  -- Безымянные параметры запроса
  S = 'INSERT INTO TTT VALUES (?, ?)'; 
  EXECUTE STATEMENT (:S) (CURRENT_TRANSACTION, CURRENT_CONNECTION)
END

При этом:

  • одновременное использование именованных и безымянных параметров в одном и том же запросе запрещено.
  • передача значений безымянным параметрам должна происходить в том же порядке, в каком они встречаются в тексте запроса.
  • присваивание значений параметров должно осуществляться при помощи специального оператора « := », аналогичного оператору присваивания в языке Паскаль.
  • если при присваивании значения параметру передается выражение (например, «P1 := GEN_ID(MY_GENERATOR, 1)» или «P1 := :I + 1»), то значение этого выражения вычисляется только один раз !

:!: Раздел оператора ON EXTERNAL DATA SOURCE позволяет выполнять cross-database запросы, т.е. запросы к другим базам данных из текущего подключения при соблюдении следующих условий:

  • если при вызове оператора EXECUTE STATEMENT пропущен раздел ON EXTERNAL DATA SOURCE и пропущен раздел AS USER, то вызываемый SQL-оператор выполняется в контексте текущего подключения и от имени текущего пользователя.
  • если при вызове оператора EXECUTE STATEMENT пропущен раздел ON EXTERNAL DATA SOURCE, но при этом присутствует раздел AS USER и параметр <user_name> равен имени текущего пользователя CURRENT_USER, то вызываемый SQL-оператор выполняется в контексте текущего подключения и от имени текущего пользователя.
  • если при вызове оператора EXECUTE STATEMENT пропущен раздел ON EXTERNAL DATA SOURCE, но при этом присутствует раздел AS USER и параметр <user_name> не равен имени текущего пользователя CURRENT_USER, то вызываемый SQL-оператор выполнится в контексте отдельного подключения к текущей базе данных. То есть для выполнения SQL-оператора сервер создаст отдельное подключение к текущей базе данных. Данная особенность может быть полезна при необходимости выполнения SQL-операторов от имени другого пользователя, аналогично как используется команда sudo командных оболочек операционных систем семейства UNIX/LINUX/FreeBSD.
  • Параметр <connection_string> раздела ON EXTERNAL DATA SOURCE должен быть в формате, используемом в API-функции сервера isc_attach_database(), в виде: [<имя_хоста (или IP-адрес)>[/<порт подключения>]:<протокол>]<имя файла базы данных (или псевдоним из aliases.conf)>. Например, «localhost:/mnt/sda1/bases/db.fdb», «192.168.0.1/3052:MAIN_CORPORATE_DATABASE», «D:\DB\MY_DATABASE.FDB».
  • В случае подключения к внешним базам данных, новое подключение использует ту же самую кодировку символов, что и у текущего подключения к базе данных. В некоторых случаях данное поведение сервера может служить источником ошибок, если у Вас кодировки символов, указанных при создании баз данных, отличаются.

:!: Раздел WITH {AUTONOMOUS | COMMON} TRANSACTION позволяет выполнять SQL-оператор, соответственно, в рамках автономной или текущей транзакции при соблюдении следующих условий:

  • если оператор EXECUTE STATEMENT выполняется в контексте автономной транзакции, то автономная транзакция будет принудительно завершена при завершении текущей транзакции.
  • если оператор EXECUTE STATEMENT выполняется в контексте автономной транзакции, то автономная транзакция будет подтверждением (commit) в случае успешного выполнения SQL-запроса или будет отменена (rollback) в случае не успешного выполнения SQL-запроса.
  • если оператор EXECUTE STATEMENT выполняется в контексте автономной транзакции, то автономная транзакция стартует с тем же уровнем изоляции данных, что и текущая, в контексте которой вызывается оператор EXECUTE STATEMENT.
  • если раздел при вызове оператора EXECUTE STATEMENT пропущен, то оператор выполняется в рамках текущей транзакции.

:!: Раздел AS USER позволяет задавать имя пользователя, от имени которого будет выполнен SQL-запрос. Если раздел при вызове оператора EXECUTE STATEMENT пропущен, то будет использоваться текущий пользователь CURRENT_USER.

:!: Раздел WITH CALLER PRIVILEGES можно использовать в том случае, когда оператор EXECUTE STATEMENT выполняется для текущего подключения к базе данных (раздел оператора ON EXTERNAL DATA SOURCE пропущен). Он позволяет выполнить SQL-запрос с привелегиями доступа к данным вызывающего EXECUTE STATEMENT PSQL-блока, хранимой процедуры или триггера. (прим.переводчика: напомним, что в первой редакции синтаксиса оператора EXECUTE STATEMENT SQL-запрос этого оператора выполнялся с привелегиями пользователя, от имени которого был запущен PSQL-блок, но при этом не учитывались привелегии самого PSQL-блока, хранимой процедуры или триггера. В некоторых случаях это заставляло давать дополнительные права пользователям на объект базы данных, что ставило под угрозу безопасность).

Пример

1. Выполнение простого, не-селективного запроса.

CREATE PROCEDURE DynamicSampleOne (
  Q_NAME VARCHAR(100)
)
AS
  DECLARE VARIABLE P_SQL_STMT VARCHAR(1024);
  DECLARE VARIABLE PAR      INTEGER;
BEGIN
  SELECT MIN(T1.SOME_FIELD) FROM SOME_TABLE T1 INTO :PAR;
  P_SQL_STMT = 'EXECUTE PROCEDURE ' || :Q_NAME || '(' || CAST(:PAR AS VARCHAR(20)) || ')';
  EXECUTE STATEMENT :P_SQL_STMT;
END

2.Выполнение простого, селективного запроса, возвращающего одну запись.

CREATE PROCEDURE DynamicSampleTwo (
  Q_TABLE_NAME VARCHAR(100)
)
AS
  DECLARE VARIABLE PAR INTEGER;
BEGIN
  EXECUTE STATEMENT 'SELECT MAX(T1.CHECKFIELD) FROM ' || :Q_TABLE_NAME || ' T1 ' INTO :PAR;
  IF (:PAR > 100) THEN
    EXCEPTION EX_OVERFLOW 'Overflow in ' || :Q_TABLE_NAME;

Обсуждение

Goland, 2008/03/24 12:23

Как вариант для There can be no dependency checks to ensure that objects referred to in the SQL statement string are not dropped from the database or modified in a manner that would break your statement. For example, a DROP TABLE request for the table used in the compiled EXECUTE PROCEDURE statement will be granted.

Не может быть выполнена проверка зависимостей, для гарантии того, что объекты, указанные в строке SQL операторов не удаляются из базы данных или не изменяются таким образом, который нарушит функционирование вашей задачи. Например, допускается выполнение команды DROP TABLE для таблицы, используемой в откомпилированной процедуре, вызываемой с помощью оператора EXECUTE PROCEDURE.

Только авторизованные участники могут оставлять комментарии.
execute_statement.txt · Последние изменения: 2013/06/18 15:27 — 80.252.147.23