Проблема с использованием «Оптимистичной блокировки» не могу обновить после просмотра таблицы - PullRequest
0 голосов
/ 10 ноября 2018

Я добавляю tcn в таблицу:

alter table accounts add TCN integer;

А UPDATE accounts set TCN = DBMS_UTILITY.GET_TIME;

И tcn не может быть нулевым alter table accounts modify TCN not null;

Я создал триггер перед обновлением

SQL> create or replace trigger acc_preupdate
  2  before update on accounts
  3  for each row
  4  begin
  5  if(:NEW.TCN != :OLD.TCN+1) THEN
  6  RAISE_APPLICATION_ERROR(-20000, 'Concurrency Failure');
  7  end if;
  8  :NEW.TCN := DBMS_UTILITY.GET_TIME;
  9  END;
 10  /

И триггер перед вставкой

SQL> create or replace trigger acc_preinsert
  2  before insert on accounts
  3  for each row
  4  begin
  5  :NEW.TCN := DBMS_UTILITY.GET_TIME;
  6  end;
  7  /

вставляю в таблицу

SQL> insert into accounts (acc_id, acc_name, acc_amount, acc_date)
  2  values(acc_seq.nextval, 'petar', 15000, sysdate);

И когда я хочу обновить таблицу, я получаю эту ошибку

SQL> update accounts
  2  set acc_amount = 1000000
  3  where acc_id = 1;
update accounts
       *
ERROR at line 1:
ORA-20000: Concurrency Failure
ORA-06512: at "PETAR1.ACC_PREUPDATE", line 3
ORA-04088: error during execution of trigger 'PETAR1.ACC_PREUPDATE'

теперь я выбираю пользователей с идентификатором 1.

select acc_name, acc_amount from accounts where acc_id = 1;

И когда я снова пытаюсь обновить таблицу, я получаю ту же ошибку.

Почему я не могу обновить таблицу?

Я использую Oracle 12c r2

1 Ответ

0 голосов
/ 10 ноября 2018

В вашем последнем выражении update вы не указываете обновление до TCN, поэтому в триггере update значение :OLD.TCN - это то, что вы вставили ранее (через триггер insert). Поскольку update явно не изменяет его, то :NEW.TCN также является тем же значением.

То есть :OLD.TCN равно :NEW.TCN, и условие if в триггере update имеет значение true, вызывая ваше пользовательское исключение.

...