Задать вопрос
sezavasasilov
@sezavasasilov

Как откатить все действия в процедуре при обработке ошибки?

Добрый день.

Есть БД на Firebird 3.
Задача: выполнить SQL-скрипт с DDL операторами внутри и в случае ошибки, полностью откатиться.
Внимательно изучив документацию, пришел к выводу, что реализация подобной затеи вполне возможна.

Установка скрипта производится с помощью процедуры:
create or alter procedure EXECUTE_SCRIPT (
    I_SCRIPT blob sub_type 1 segment size 80 not null)
returns (
    ERR smallint)
as
declare variable V_COMMAND blob sub_type 1 segment size 80;
begin
  ERR = 0;
  begin
    for
      select COMMAND
      from SPLIT_SCRIPT(:I_SCRIPT)
      into :V_COMMAND
    do
      execute statement(V_COMMAND);

    when any do
      ERR = 1;
  end
end


В данном случае SPLIT_SCRIPT разбивает исходный скрипт на отдельные команды, удаляет смену терминатора в начале, коммит в конце и удаляет сам терминатор в конце команд.

Вот скрипт, который хочу выполнить:
Полный текст скрипта
set term ^;

create table test_table1 (
    id integer,
    name varchar(30)
)^

create or alter procedure test_proc1 (
    I_ID integer,
    I_NAME varchar(30) character set UTF8)
returns (
    O_MSG varchar(30) character set UTF8)
as
begin
  insert into test1 (id, name)
  values(:i_id, :i_name);
  o_msg = 'Запись №' || i_id || ' с именем ' || i_name || ' вставлена!';
  suspend;
end^

commit^

Результат выполнения процедуры SPLIT_SCRIPT
create table test_table1 (
    id integer,
    name varchar(30)
)

create or alter procedure test_proc1 (
    I_ID integer,
    I_NAME varchar(30))
returns (
    O_MSG varchar(30))
as
begin
  insert into test1 (id, name)
  values(:i_id, :i_name);
  o_msg = 'Запись №' || i_id || ' с именем ' || i_name || ' вставлена!';
  suspend;
end


Как видите, во второй команде (создание процедуры) намеренно допущена ошибка в названии таблицы при вставке, чтобы вызвать исключение.

Далее несколько цитат из документации (стр. 495):
Внутренне автоматические точки сохранения используется для:
• отмены всех действий внутри блока BEGIN ... END, где происходит исключение;

Сами по себе блок BEGIN..END не создаёт автоматическую точку сохранения. Она создаётся
только в блоках, которых присутствует блок WHEN для обработки исключений или ошибок.


На первый взгляд условия соблюдены, ничего криминального, однако при выполнении процедуры EXECUTE_SCRIPT и последующем коммите, таблица все-таки создается, чего быть не должно.

Или я что-то упустил?
  • Вопрос задан
  • 1057 просмотров
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы