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