Формат блока кода

Определение описания блока кода процедурного языка.

     
< блок кода >::=
< вложенный блок >::=

Синтаксические правила

  1. Представления тела процедуры в виде иерархии вложенных блоков возникает при необходимости локализации обработки исключений, например, исключение NULLDATA может генерироваться в каждом вложенном блоке и в каждом из них должно обрабатываться по собственному правилу.

  2. Если вложенный блок содержит < блок обработки исключений >, или блок обработки содержит оператор RESIGNAL, то возникшие в этом вложенном блоке исключения обрабатываются сначала в его < блоке обработки исключений >. Если вложенный блок не содержит < блок обработки исключений > или исключение не может быть обработано в его < блоке обработки исключений >, то при запуске ядра СУБД ЛИНТЕР с ключом /COMPATIBILITY=RESIGNAL_ALL исключение передается по иерархии на следующие вложенные блоки (т.е. при таком запуске ядра СУБД нет необходимости в каждом вложенном блоке явно выполнять оператор RESIGNAL), в противном случае обработка исключения сразу передается на < блок обработки исключений > самого верхнего уровня (если этот < блок обработки исключений > задан).

  3. На любом уровне вложенности при отсутствии ключа /COMPATIBILITY=RESIGNAL_ALL все неопределенные в блоке описаний исключения, кроме критичных для исполнения, игнорируются. Критичными считаются следующие исключения: DIVZERO, UNDEFPROC, BADPARAM, BADRETVAL, BADCURSOR, CURNOTOPEN, NOMEM, OVERFLOW. Если происходит такое исключение, и для него нет обработчика, автоматически выполняется завершение процедуры с передачей исключений выше, в блок вызвавшей процедуры, из которого произошел вызов (с NULL-значением в качестве возвращаемого значения) (см. также оператор RESIGNAL).

  4. Исключения, не относящиеся к списку критичных (DIVZERO, UNDEFPROC, BADPARAM, BADRETVAL, BADCURSOR, CURNOTOPEN, OVERFLOW), например, NULLDATA, при отсутствии ключа /COMPATIBILITY=RESIGNAL_ALL, возникшие в блоке CODE...END, не попадут в обработчик предыдущего уровня.

    Например, процедура

    CREATE OR REPLACE PROCEDURE TST_CODE() RESULT INT FOR DEBUG
    DECLARE
      VAR v, z int;
      EXCEPTION NULLDATA for NULLDATA;
    CODE
      v:=3;
      CODE
        z:= NULL;
        v:= z + v;
      END
      RETURN 0;
    EXCEPTIONS
      WHEN NULLDATA THEN
        RETURN 1;
    END;
    
    CALL tst_code();
    result=1

    вернёт результат 1, т.к. во вложенном блоке CODE… END нет своего обработчика исключений, и сгенерированное в нем исключение будет передано на обработку на предшествующий по иерархии уровень.

    А процедура:

    CREATE OR REPLACE PROCEDURE tst_code() RESULT INT FOR DEBUG
    DECLARE
      VAR v, z INT;
      EXCEPTION NULLDATA FOR NULLDATA;
    CODE
      v:=3;
      CODE
        z:= NULL;
        v:= z + v;
      EXCEPTIONS
        WHEN NULLDATA THEN
          RETURN 0;
      END
    EXCEPTIONS
      WHEN NULLDATA THEN
        RETURN 1;
    END;
    
    CALL tst_code();
    result=0

    вернёт результат 0, т.к. во вложенном блоке CODE… END есть свой обработчика исключений, поэтому сгенерированное в нем исключение не будет передано на обработку на предшествующий по иерархии уровень.

Примеры

1)
create or replace procedure tst_code() result int for debug
declare
  var make char(20);
  exception no_data_found for 2;
  exception notab for 2202;
  var val_ret int;
-- code1 - первый вложенный блок
code
  code
    execute "select distinct model from auto where make like 'F%'and personid=90;" into make;
  exceptions
    when no_data_found then
      val_ret:=-1;
      goto ret;
    when notab then
     val_ret:=-2;
     goto ret;
  end
-- code2 - второй вложенный блок
code
  execute "select distinct model from auto where make like 'F%'and personid=-1" into make;
  exceptions
    when no_data_found then
      val_ret:=-3;
      goto ret;
    when notab then
      val_ret:=-4;
      goto ret;
  end
  ret: return val_ret;
end;

call tst_code();
result -3

2)
create or replace procedure tst_code() result int for debug
declare
  var make char(20);
  exception no_data_found for 2;
  exception notab for 2202;
  var val_ret int;
// code1 - первый вложенный блок
code
  val_ret:=100;
  code
    execute "select distinct model from auto where make like 'F%'and personid=-1;" into make;
    code
      execute "select distinct model from auto where make like 'F%'and personid=90;" into make;
    exceptions
      when no_data_found then
        val_ret:=-3;
        goto ret;
      when notab then
        val_ret:=-4;
        goto ret;
    end
  exceptions
    when no_data_found then
      val_ret:=-1;
      goto ret;
    when notab then
      val_ret:=-2;
      goto ret;
  end
  ret: return val_ret;
end;

call tst_code();
result -1