В Firebird 1.5 появился оператор LEAVE для выхода из блоков. Он заменил оператор BREAK, который был частично реализован в версии 1.0.x. Вот пример его использования в цикле WHILE нашей процедуры IS_PORK_SAFE:
WHILE (SI < 9) DO
BEGIN
SI = SI + 1; /* арифметическое выражение */
IF (SUBSTRING(SMONTH FROM 1 FOR 1) = 'R') THEN
BEGIN
RESPONSE = 'YES'; /* простая константа */
LEAVE;
END
SMONTH = SUBSTRING(SMONTH FROM 2);
/* функциональное выражение */
END
LEAVE приводит к выходу из цикла - в нашем случае останавливается проверка букв слова на символ "R". Если ветвь, содержащая оператор LEAVE, не выполняется, то выполнение продолжается до конца цикла.
Оператор EXCEPTION останавливает выполнение и передает управление первому блоку обработки исключений (блоку, начинающемуся с ключевого слова WHEN), который может обработать исключение. Если для этого исключения не найден обработчик, управление передается финальному оператору END и процедура завершается аварийно. Когда происходит такое, один или более кодов исключения передается назад клиенту через вектор состояния ошибок (массив).
Оператор EXCEPTION используется в блоке IF ... THEN ... ELSE для вызова пользовательских исключений, предварительно определенных как объекты базы данных. Сервер Firebird вызывает свои собственные исключения для SQL и контекста ошибок. Поток управления в этих случаях точно такой же, как и при вызове пользовательских исключений.
Синтаксис и техники вызова и обработки исключений описаны в главе 32.
EXECUTE STATEMENT
Firebird 1.5 вводит расширение PSQL, поддерживающее выполняемые строки. Приложение или процедура могут передать оператор DSQL (DDL или DML) в виде строки входного аргумента (либо процедура может сконструировать эту строку как локальную переменную) для выполнения с использованием EXECUTE STATEMENT.
EXECUTE STATEMENT добавляет гибкости хранимым процедурам и триггерам, но с высоким риском ошибок. Возвращаемые значения жестко проверяются на типы данных, чтобы избежать непредсказуемых исключений преобразования данных. Например, строка '1234' может быть преобразована в целое, a 'abc' вызовет ошибку преобразования. Во время компиляции такая строка не может быть проанализирована и проверена.
Синтаксис:
[FOR] EXECUTE STATEMENT <строка>
[INTO :переменная1 [, :переменная2 [, :переменнаяN ] ] DO
<составной-оператор>];
<составной-оператор> = {оператор \ блок-операторов}
Конструирование выражения или строковой переменной для создания оператора DSQL в строке аргумента должно быть завершено к моменту выполнения EXECUTE STATEMENT. Выполняемый оператор DSQL в строке аргумента не может содержать никаких заменяемых параметров.
В своей простейшей форме EXECUTE STATEMENT выполняет оператор SQL, запрашивающий операцию, которая не возвращает строк данных, а именно:
* INSERT, UPDATE, DELETE;
* EXECUTE PROCEDURE;
* любой оператор DDL за исключением CREATE/DROP DATABASE. Например:
CREATE PROCEDURE EXEC_PROC (PROC_NAME VARCHAR (31))
AS
DECLARE VARIABLE SQL VARCHAR(1024);
DECLARE VARIABLE . . .
BEGIN
. . .
SQL = 'EXECUTE PROCEDURE ' || PROC_NAME;
EXECUTE STATEMENT SQL;
END ^
Процедура вызывает следующее:
EXECUTE PROCEDURE EXEC_PROC ( ' PROJECT_MEMBERS ' ) ;
Следующий фрагмент кода показывает, как выполнять строку оператора SELECT, который возвращает одну строку в набор переменных. Как и любой другой оператор SELECT в модуле PSQL, он вызовет исключение, если оператор вернет множество строк. Здесь мы также можем выполнить нечто невозможное в обычном PSQL: выполнить операцию, включающую таблицу или столбец, чье имя неизвестно во время компиляции:
CREATE PROCEDURE SOME_PROC
(TABLE_NAME VARCHAR (31), COL_NAME VARCHAR (31))
AS
DECLARE VARIABLE PARAM DATE;
BEGIN
EXECUTE STATEMENT 'SELECT MAX ( ' || COL_NAME || ') FROM ' || TABLE_NAME
INTO : PARAM;
. . .
FOR SELECT . . . . FROM . . . .
WHERE END_DATE = : PARAM
INTO ... DO
. . .
END ^
Синтаксис EXECUTE STATEMENT также поддерживает выполнение оператора SELECT внутри цикла FOR для возвращения по одной строки за раз в список переменных. Не существует ограничений на используемый оператор SELECT, однако помните, что во время компиляции синтаксический анализатор не может проверить содержимое строки.
CREATE PROCEDURE DYNAMIC_SAMPLE (
TEXT_COL VARCHAR(31),
TABLE_NAME VARCHAR (31))
RETURNS (LINE VARCHAR(32000))
AS
DECLARE VARIABLE ONE_LINE VARCHAR (100);
DECLARE VARIABLE STOP_ME SMALLINT;
BEGIN
LINE = ' ' ;
STOP_ME = 1;
FOR EXECUTE STATEMENT
'SELECT ' || TEXTCOL || ' FROM ' || TABLE_NAME
INTO :ONE_LINE DO
BEGIN
IF (STOP_ME > 320) THEN
EXIT;
IF (ONE_LINE IS NOT NULL) THEN
LINE = LINE || ONE_LINE || ' '
STOP_ME = STOP_ME + 1;
END
SUSPEND;
END ^