Oracle SQL - 我可以在"之前返回"列值的状态

时间:2016-11-10 08:25:44

标签: sql oracle

假设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等效的方法来实现这一点,所以我不必先做一个"选择"只是为了获得之前的价值?

3 个答案:

答案 0 :(得分:11)

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上测试

答案 1 :(得分:1)

我相信你不能用一个简单的SQL语句来做(我错了,看到Mikes的回答:-))

一种方法可能是使用另一个列和一个触发器;例如,假设您有一个包含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);

运行更新时,旧值存储在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

但是,鉴于这需要在表中添加一个列和一个触发器,我认为这个解决方案比我想要在生产数据库中使用的更多是

答案 2 :(得分:1)

如果没有太多更新,您可以循环更新并获取旧值:

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;
/