Oracle SQL - можно вернуть состояние "до" значения столбца

Предположим следующую строку в myTable:

id     =  1
letter = 'a'

В Oracle можно легко сделать следующее:

update myTable set
  letter = 'b'
where id   = 1
returning letter 
into myVariable;

и myVariable будет удерживать значение 'b'.

То, что я ищу, - это способ возврата знака "до"

т. замените предыдущее обновление на:

update myTable set
  letter = 'b'
where id   = 1
returning letter "before the update"
into myVariable;

, а myVariable должен удерживать значение 'a';

Я понимаю, что T-SQL может достичь этого с помощью предложения OUTPUT.

Есть ли эквивалентный способ Oracle для достижения этого, поэтому мне не нужно сначала делать "выбор", чтобы получить значение до?

Ответ 1

update
  (
   select T.*, (select letter from DUAL) old_letter
     from myTable T
    where id=1
  )
   set letter = 'b'
returning old_letter into myVariable;

Протестировано на Oracle 11.2

Ответ 2

Я считаю, что вы не можете сделать это с помощью простого оператора SQL (и я ошибаюсь, учитывая ответ Майкса:-))

Один из способов - использовать другой столбец и триггер; например, скажем, что у вас есть таблица со столбцом a, вы можете добавить еще один столбец old_a для хранения старого значения a и заполнить его триггером:

create table testUpdate(a number, old_a number);
create or replace trigger trgUpdate 
before update on testUpdate
for each row
begin
    if :new.a != :old.a then /* assuming not null values for simplicity */
        :new.old_a := :old.a;
    end if;
end; 
insert into testUpdate values (1, null);

При запуске обновления старое значение сохраняется в столбце th old_a и возвращается в returning предложение

SQL> declare
  2      vA number;
  3  begin
  4      update testUpdate
  5      set a = 9
  6      returning old_a
  7      into vA;
  8      --
  9      dbms_output.put_line(vA);
 10  end;
 11  /
1

Однако, учитывая, что для добавления таблицы необходимо добавить столбец и триггер, я считаю это решение более упражнением, чем то, что я хотел бы иметь в производственной БД

Ответ 3

Если обновлений не много, вы можете выполнить обновление в цикле и получить старые значения:

declare
CURSOR c IS SELECT letter, id FROM myTable 
  FOR UPDATE OF letter;
begin
  open c;
  for x in c loop
     -- old value is in x.letter. You can assign it here
     update myTable set letter = 'b' where id = x.id;      
  end loop;
  commit;
  close c;
end;
/