(PLSQL)在Oracle on-update触发器中测试更改值的最简单表达式是什么?

时间:2010-09-09 16:15:41

标签: oracle plsql triggers

这是一个布尔表达式,可以解决这个问题:

nvl(:new.location != :old.location, (:new.location is null) != (:old.location is null))

但我想认为有一个更简单的表达方式。有什么想法吗?

4 个答案:

答案 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