2010-09-09 103 views

回答

1
decode(:old.location, :new.location, 1) is null 

编辑:它可能更清楚地说:

decode(:old.location, :new.location, null, 1) = 1 
+0

我喜欢第一个版本的简单性。不幸的是,它的作用并不是很明显,但有了足够的使用,我想它可能会变得习惯。它很简单,很容易被识别。 – rattigan 2010-10-21 20:31:48

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)。

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

我建议你花额外的第二输入它的逻辑方式。你的代码看起来更好,运行速度更快。

+0

我不知道为什么,但在我们的环境11g R1中却是相反的。第一个nvl解决方案花费0,125秒,第二个解决方案花费0,235秒。如果我注释掉“j:= 1”,那么它们大约快0.05秒。 – 2010-10-29 08:06:20

0

也许你只想触发器在所有值都发生改变时触发?如果是这样,创建触发器时最好使用以下语法:

CREATE OR REPLACE TRIGGER DepartTrigger BEFORE UPDATE OF location ON Department 
+0

...尽管您仍然需要检查更改,因为“更新部门集合位置=位置”会触发该触发器。 – 2010-09-10 08:37:16