0

我试图创建触发器,如果​​角色是公司,它会提醒用户避免 address1 中的空值。这就是我结束的地方:

CREATE OR REPLACE TRIGGER "SCHEMA"."ADDRESS_VALUE"                          
BEFORE INSERT OR UPDATE ON "SCHEMA"."TABLE1"
FOR EACH ROW
DECLARE
  ADDRESS TABLE1.ADDRESS1%TYPE;   
  V_CNT NUMBER; 
BEGIN
  ADDRESS := :NEW.ADDRESS1;
  IF :OLD.ADDRESS1 = ADDRESS THEN
    RETURN;
  END IF;

  SELECT COUNT(1)
    INTO V_CNT    
    FROM SCHEMA.TABLE2 
   WHERE ROLE = 'COMPANY';

  IF V_CNT > 0 THEN 
    RAISE_APPLICATION_ERROR(-20101,' ADDRESS IS MANDATORY');              
  END IF;
END;

这似乎工作正常并给出一条消息,如果用户试图将其保留为空,则“地址是强制性的”,但即使他们尝试在 address1 中添加一些内容,消息仍然会不断出现。它有点卡在那里,即使必填字段为 <> null,也不允许继续。怎么了?

你能帮我解决这个烦人的问题吗?谢谢。

Oracle 11g 正在使用中。

问候,几乎是第一次触发

4

1 回答 1

0

您的触发器有几个问题。看来您有一个条件非空列,充其量是一个糟糕的设计。“COMPANY”角色的协助决定了 address1 是否允许为空。如果它的角色完全存在,它不必与正在处理的行相关,那么 Address1 对于任何行都不能为空。那么,当最初添加角色时,您将如何处理现有的 null address1 行。
存在不存在的插入旧记录的问题。你测试看看address1是否改变了;我想您可以声称现有技术上不存在的形式可以称为已更改。它会起作用,但绝对不是推荐的方法。纠正我们将完全摆脱它。最后,您的主要抱怨是即使知道 address1 不为空,也会引发异常。这是因为您甚至没有测试它的内容是否为空。如果“公司”角色存在,您会抛出异常。本质上,您的触发器说“如果 table2 中存在角色“COMPANY”,则不允许在 table1 上插入,也不允许更新 table1 中现有的 address1 值”。
尝试以下操作:

CREATE OR REPLACE TRIGGER "SCHEMA"."ADDRESS_VALUE"                          
BEFORE INSERT 
    OR UPDATE of address1 
    ON "SCHEMA"."TABLE1"
FOR EACH ROW
DECLARE 
  V_CNT NUMBER; 
BEGIN
  if :new.address1 is null
  then 
      SELECT COUNT(1)
        INTO V_CNT    
        FROM SCHEMA.TABLE2 
       WHERE ROLE = 'COMPANY';

      IF V_CNT > 0 THEN 
        RAISE_APPLICATION_ERROR(-20101,' ADDRESS IS MANDATORY');              
      END IF;
  end if;
END; 

有什么改变?首先注意触发器标头的变化,特别是 UPDATE 规范。修订消除了您检查更新是否已更改的需要。如果它没有改变触发器不会触发。其次,仅当新地址 1 为空时才检查角色的存在,如果它不为空,则角色存在与否无关紧要。
最后,存在与“COMPANY”角色无关的行的潜在问题,但由于它存在而失败允许空能力。我们需要定义表和 DDL 之间的关系,以便他们都对此发表评论。

于 2019-10-01T17:39:11.513 回答