Выполнение запроса
Назначение
Оператор запроса предназначен для организации непосредственной работы с СУБД.
В хранимых процедурах допустимы два вида запросов: претранслируемые, которые разбираются на этапе трансляции процедуры, и динамические, которые формируются, транслируются на этапе выполнения процедуры и сразу же выполняются. Приоритет обоих типов запросов наследуется от родительского канала. Претранслируемые и динамические запросы делятся на запросы возвращающие выборку данных и не возвращающие выборку данных. Запросы, возвращающие выборку данных, могут быть использованы в курсорах (см. пункт Открытие курсора). Текст запроса должен оканчиваться знаком (;) и быть заключенным в двойные апострофы (").
В качестве претранслируемых запросов обычно используются запросы с параметрами. Запрос транслируется и сохраняется в БД. На этапе выполнения к претранслированному запросу привязываются вычисленные параметры, если они есть.
В качестве динамических запросов используются запросы, текст которых на момент трансляции процедуры неизвестен (он формируется в виде символьного выражения хранимой процедурой в процессе её выполнения, поэтому синтаксический и семантический контроль такого запроса производится при выполнении процедуры).
Если при выполнении запроса обнаруживается ошибка, происходит исключение с соответствующим кодом завершения.
Синтаксис
<выполнение претранслируемого запроса>::=
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