Выполнение запроса
Назначение
Оператор запроса предназначен для организации непосредственной работы с СУБД.
В хранимых процедурах допустимы два вида запросов: претранслируемые, которые разбираются на этапе трансляции процедуры, и динамические, которые формируются, транслируются на этапе выполнения процедуры и сразу же выполняются. Приоритет обоих типов запросов наследуется от родительского канала. Претранслируемые и динамические запросы делятся на запросы возвращающие выборку данных и не возвращающие выборку данных. Запросы, возвращающие выборку данных, могут быть использованы в курсорах (см. пункт Открытие курсора). Текст запроса должен оканчиваться знаком (;) и быть заключенным в двойные апострофы (").
В качестве претранслируемых запросов обычно используются запросы с параметрами. Запрос транслируется и сохраняется в БД. На этапе выполнения к претранслированному запросу привязываются вычисленные параметры, если они есть.
В качестве динамических запросов используются запросы, текст которых на момент трансляции процедуры неизвестен (он формируется в виде символьного выражения хранимой процедурой в процессе её выполнения, поэтому синтаксический и семантический контроль такого запроса производится при выполнении процедуры).
Если при выполнении запроса обнаруживается ошибка, происходит исключение с соответствующим кодом завершения.
Синтаксис
< выполнение претранслируемого запроса >::= EXECUTE < запрос > [{,|USING} < параметр > [, …]] [INTO < переменная > [, …]]; < выполнение динамического запроса >::= EXECUTE DIRECT < выражение символьного типа > [{,|USING} < параметр > [, …]] [INTO < переменная > [, …]];
Описание
-
Оператор EXECUTE позволяет выполнить любой запрос (в том числе и SELECT) по отдельному каналу СУБД ЛИНТЕР, который неявно открывается при обработке этого оператора (его закрытие производится в зависимости от обработки транзакции).
-
< Запрос > должен быть обрамлен двойными апострофами «"» и оканчиваться «;».
-
Параметр INTO < переменная > [, …] задает список скалярных переменных, в который должны быть загружены выбираемые по < запросу > значения. Количество и тип данных скалярных переменных должны соответствовать количеству и типу данных выбираемых по < запросу > значений. Запрос выборки должен возвращать только одну запись (при возвращении более одной записи в скалярную переменную будет сгенерировано исключение BADPARAM).
Для < переменной > допускаются все простые типы данных, кроме BLOB и EXTFILE.
Примечание
Если результат < запроса > – пустая выборка, то < переменная > сохранит значение, которое было перед выполнением EXECUTE … INTO …
-
Если задана опция DIRECT, текст запроса при создании процедуры не проверяется, а передается напрямую ядру СУБД ЛИНТЕР при выполнении процедуры, т.е. синтаксический и семантический контроль запроса выполняется при исполнении процедуры.
Если опция DIRECT не указана, синтаксический и семантический контроль < запроса > выполняется на этапе создания процедуры.
Сравните (таблица t1 отсутствует в БД):
CREATE OR REPLACE PROCEDURE tst_dir() RESULT NUMERIC for debug DECLARE VAR VINST_ID NUMERIC; CODE EXECUTE "SELECT a from t1;" INTO VINST_ID; //ошибка трансляции EXECUTE DIRECT "SELECT a from t1;" INTO VINST_ID; //без ошибки трансляции RETURN VINST_ID; END;
-
Если заданы опции DIRECT и < параметры >, то во время выполнения оператора сначала выполняется трансляция < запроса >, затем привязка параметров и выполнение < запроса >.
Примечание
Рекомендуется использовать опцию DIRECT только в ситуациях, когда статическая компиляция запроса невозможна – например, при динамическом указании имени таблицы или имен столбцов. Нежелательно использование оператора EXECUTE с опцией DIRECT для подстановки параметров в запрос, поскольку это гораздо эффективнее выполняется при помощи статического EXECUTE.
-
В результате выполнения оператора EXECUTE может возникнуть исключение, соответствующее коду завершения СУБД ЛИНТЕР (так же, как и при выполнении операторов OPEN, FETCH и CLOSE).
-
Запрос может транслировать один пользователь, а выполнять другой (в случае, если запрос указан в команде EXECUTE, и процедура выполняется не в режиме AS OWNER). Проверки наличия привилегий при этом проверяются для выполняющего пользователя, а не для транслирующего. От транслирующего пользователя берутся только умолчания (прежде всего его текущая схема).
Есть различие с действием команды EXECUTE DIRECT при выполнении процедуры не в режиме AS OWNER – там и права проверяются для выполняющего пользователя, и умолчания берутся его же.
Пользователь CREATOR: создает процедуру с командой: EXECUTE "SELECT * FROM TBL;" Пользователь EXECUTOR: выполняет эту процедуру без AS OWNER Результат: запрос от имени EXECUTOR подается к таблице CREATOR.TBL Пользователь CREATOR: создает процедуру с командой: EXECUTE DIRECT "SELECT * FROM TBL;" Пользователь EXECUTOR: выполняет эту процедуру без AS OWNER Результат: запрос от имени EXECUTOR подается к таблице EXECUTOR.TBL
Примеры
1) execute "update tab1 set s = ? where current of \"CURS\";" using sum; 2) execute "create table test(i int);"; 3) var cnt int; // … execute "select count(*) from auto;" into cnt; // 4) create or replace procedure tst() result char(50) for debug declare var mdl char(20); // var sale int; // code execute "select model, year+1900 from auto where personid=500;" into mdl, sale; // return mdl+" дата продажи; "+ itoa(sale); // end; 5) create or replace table test(i int, utf nchar(10), v_utf nvarchar(20)); insert into test (i, utf, v_utf) values(1, n'342f', n'56ffca45'); insert into test (i, utf, v_utf) values(2, n'cccc', n'56745333fffa'); create or replace procedure prc_test() result nchar(20) for debug declare var ch nvarchar(50); // code execute "select v_utf from test where i=2;" into ch; // return ch; // end; execute prc_test(); Return value = 56745333fffa 6) create table aaa (i int, ch char(3)); insert into aaa values(1, 'abc'); insert into aaa values(2, 'def'); insert into aaa values(3, 'ghi'); create or replace procedure prc_test(in n int) result char(15) for debug declare var ch typeof(aaa.ch);// code execute "select ch from aaa where i=:p1;" using n into ch;// return ch;// end; execute prc_test(2); drop table aaa; Результат работы примера: Return value = def 7) execute block result typeof( person.fmlystat ) declare var age integer;// var stat typeof(person.fmlystat);// code execute "update person set age=40 where name='kim' and firstnam='eddie'";// execute "select age, fmlystat from person where name=? and firstnam=?" using "kim", "eddie" into age, stat;// execute "update person set age=? where name=? and firstnam=?" using age + 1, "kim", "eddie";// execute "select age from person where name=? and firstnam=?", "kim", "eddie" into age;// return stat;// end; 8) create or replace procedure report(in Модель char(15); in Цвет char(10)) result int for debug declare var Количество int; // var Запрос char(100); // code Запрос:="select count(*) from auto where model='"+ Модель+ "'and color='" + Цвет+"';";// execute direct Запрос into Количество; // return Количество; // end; execute report('PANTERA','BLACK'); return value = 5