这是一个布尔表达式,可以解决这个问题:
nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null))
但我想认为有一个更简单的表达方式。有什么想法吗?
答案 0 :(得分:3)
这些较短的方法都有几个缺点。 它们很慢,不直观,可能有错误(尽可能避免魔法值), 比正常条件更专有,如AND / OR / IS NULL / IS NOT NULL。
NVL,DECODE,COALESCE等可能比您想象的更贵。
我在很多不同的背景下都看过很多次,这是一个简单的例子:
--Shorter method: Takes about 0.45 seconds
declare
j number;
begin
for i in 1 .. 1000000 loop
j := i;
if nvl(i <> j, (i is null) <> (j is null)) then
null;
end if;
end loop;
end;
/
--Normal method: Takes about 0.25 seconds
declare
j number;
begin
for i in 1 .. 1000000 loop
j := i;
if i <> j or (i is null and j is not null) or (i is not null and j is null) then
null;
end if;
end loop;
end;
/
我建议您花费额外的时间以逻辑方式键入它。您的代码看起来会更好并且运行得更快。
答案 1 :(得分:2)
你可以像这样创建一个重载的包函数:
package p is
function changed (p_old varchar2, p_new varchar2) return voolean;
function changed (p_old number, p_new number) return voolean;
function changed (p_old date, p_new date) return voolean;
end;
然后在触发器中调用它:
if p.changed(:old.location,:new.location) then ...
或者你可以这样做:
if nvl(:old.location,'£$%') != nvl(:new.location,'£$%') then ...
当然,您必须选择一个永远不会成为真实位置的值,这在某些情况下可能会非常棘手。对于VARCHAR2,您可以为列大小选择一个太长的值(除非恰好是4000)。
答案 2 :(得分:1)
decode(:old.location, :new.location, 1) is null
编辑:可能更清楚地说:
decode(:old.location, :new.location, null, 1) = 1
答案 3 :(得分:0)
如果值已经改变,也许你只想触发触发器?如果是这样,您最好在创建触发器时使用此语法:
CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department