Вот вводная: create sequence test_gen; recreate table test_row (id int not null, did int not null, pid int not null, dep int not null ); alter table test_row add constraint pk_test_row primary key(id); create unique index ix_test_row1 on test_row(did, pid, dep); commit; insert into test_row(id, did, pid,dep) values(1, 2, 3, 4); commit; Вот собственно блок: set term !!; execute block returns(id int, did int, dep int, pid int) as declare variable xid int; begin select id,did, pid,dep from test_row where id=(select min(id) from test_row) into :xid, :did, pid, :dep; while (1=1) do begin delete from test_row r where r.id = :xid; insert into test_row(id, did, dep, pid) values (gen_id(test_gen, 1), :did, :dep, :pid); suspend; when any do exception; end end !! Вопрос на засыпку: почему он перед ошибкой возвращает две строки? Совершенно аналогичная процедура: create or alter procedure sp_test returns(id int, did int, dep int, pid int) as declare variable xid int; begin select id,did, pid,dep from test_row where id=(select min(id) from test_row) into :xid, :did, pid, :dep; while (1=1) do begin delete from test_row r where r.id = :xid; insert into test_row(id, did, dep, pid) values (gen_id(test_gen, 1), :did, :dep, :pid); suspend; when any do exception; end end !! select * from sp_test !! Возвращает одну строку. Чего я не понимаю?
А при чём здесь он, если идёт выброс нарушения уникальности ix_test_row1, а не pk_test_row? Первый delete полностью очищает таблицу (поскольку в ней всего одна запись (1, 2, 3, 4)). Далее в неё пытаются вставиться (1, 2, 3, 4) и (2, 2, 3, 4) в EB. Первая вставка успешна, вторая вставка обламывается, транзакция полностью откатывается, восстанавливая запись (1, 2, 3, 4). Последующий вызов процедуры снова удаляет запись (1, 2, 3, 4) и пытается вставить записи (3, 2, 3, 4) и (4, 2, 3, 4). Первая вставка успешна, вторая вставка обламывается, транзакция откатывается. Так почему блок возвращает две записи, а процедура - одну?
А ты всё же посмотри на значения генератора. хинт1: выполни exec block два раза подряд хинт2: в начальном скрипте используй генератор для инсерта