Выполнение запроса

Назначение

   

Оператор запроса предназначен для организации непосредственной работы с СУБД.

В хранимых процедурах допустимы два вида запросов: претранслируемые, которые разбираются на этапе трансляции процедуры, и динамические, которые формируются, транслируются на этапе выполнения процедуры и сразу же выполняются. Приоритет обоих типов запросов наследуется от родительского канала. Претранслируемые и динамические запросы делятся на запросы возвращающие выборку данных и не возвращающие выборку данных. Запросы, возвращающие выборку данных, могут быть использованы в курсорах (см. пункт Открытие курсора). Текст запроса должен оканчиваться знаком (;) и быть заключенным в двойные апострофы (").

В качестве претранслируемых запросов обычно используются запросы с параметрами. Запрос транслируется и сохраняется в БД. На этапе выполнения к претранслированному запросу привязываются вычисленные параметры, если они есть.

В качестве динамических запросов используются запросы, текст которых на момент трансляции процедуры неизвестен (он формируется в виде символьного выражения хранимой процедурой в процессе её выполнения, поэтому синтаксический и семантический контроль такого запроса производится при выполнении процедуры).

Если при выполнении запроса обнаруживается ошибка, происходит исключение с соответствующим кодом завершения.

Синтаксис

           
< выполнение претранслируемого запроса >::=
    EXECUTE < запрос > [{,|USING} < параметр > [, …]] [INTO < переменная > [, …]];

< выполнение динамического запроса >::=
    EXECUTE DIRECT < выражение символьного типа > [{,|USING} < параметр > [, …]] [INTO < переменная > [, …]];

Описание

  1. Оператор EXECUTE позволяет выполнить любой запрос (в том числе и SELECT) по отдельному каналу СУБД ЛИНТЕР, который неявно открывается при обработке этого оператора (его закрытие производится в зависимости от обработки транзакции).

  2. < Запрос > должен быть обрамлен двойными апострофами «"» и оканчиваться «;».

  3. Параметр INTO < переменная > [, …] задает список скалярных переменных, в который должны быть загружены выбираемые по < запросу > значения. Количество и тип данных скалярных переменных должны соответствовать количеству и типу данных выбираемых по < запросу > значений. Запрос выборки должен возвращать только одну запись (при возвращении более одной записи в скалярную переменную будет сгенерировано исключение BADPARAM).

    Для < переменной > допускаются все простые типы данных, кроме BLOB и EXTFILE.

    Примечание

    Если результат < запроса > – пустая выборка, то < переменная > сохранит значение, которое было перед выполнением EXECUTE … INTO …

  4. Если задана опция 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;
  5. Если заданы опции DIRECT и < параметры >, то во время выполнения оператора сначала выполняется трансляция < запроса >, затем привязка параметров и выполнение < запроса >.

    Примечание

    Рекомендуется использовать опцию DIRECT только в ситуациях, когда статическая компиляция запроса невозможна – например, при динамическом указании имени таблицы или имен столбцов. Нежелательно использование оператора EXECUTE с опцией DIRECT для подстановки параметров в запрос, поскольку это гораздо эффективнее выполняется при помощи статического EXECUTE.

  6. В результате выполнения оператора EXECUTE может возникнуть исключение, соответствующее коду завершения СУБД ЛИНТЕР (так же, как и при выполнении операторов OPEN, FETCH и CLOSE).

  7. Запрос может транслировать один пользователь, а выполнять другой (в случае, если запрос указан в команде 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