在Oracle中创建触发器以检查表之间的日期

时间:2017-03-12 16:30:49

标签: oracle triggers insert

我的Oracle DB中有2个表

CLIENT_ID(PK) -  INSERT_DATE

    1         -  1/1/2017  


CLIENT_ID(FK) -  EXIT_DATE

    1         -  5/1/2017

我想创建一个Before Insert Trigger,如果我尝试在EXIT_DATE上插入一个早于INSERT_DATE列的日期,则会显示错误。

例如,如果我尝试插入31/12/2016,它将显示错误“退出日期不能早于INSERT DATE”我的问题还在于触发器必须在2个表之间匹配Client_ID。 (我使用的是Oracle 11g)

1 个答案:

答案 0 :(得分:1)

已修改,其中包含FOREIGN KEY阻止孤儿CLIENT_ID的信息。

要生成强制执行您所描述的规则的触发器,以下内容将起作用 首先,创建一些测试表:

CREATE TABLE INSERT_TABLE(
  CLIENT_ID NUMBER NOT NULL PRIMARY KEY,
  INSERT_DATE DATE NOT NULL
);

CREATE TABLE EXIT_TABLE(
  CLIENT_ID NUMBER NOT NULL REFERENCES INSERT_TABLE(CLIENT_ID),
  EXIT_DATE DATE NOT NULL
);
CREATE INDEX EXIT_INSERT_FKI ON EXIT_TABLE(CLIENT_ID);

然后,应用触发器:

CREATE OR REPLACE TRIGGER EXIT_AFTER_INSERT_ENFORCER
BEFORE INSERT ON EXIT_TABLE
FOR EACH ROW
  DECLARE
    V_INSERT_DATE DATE;
  BEGIN
    SELECT INSERT_TABLE.INSERT_DATE
    INTO V_INSERT_DATE
    FROM INSERT_TABLE
    WHERE INSERT_TABLE.CLIENT_ID = :NEW.CLIENT_ID;

    IF :NEW.EXIT_DATE < V_INSERT_DATE
    THEN RAISE_APPLICATION_ERROR(-20100, 'EXIT DATE cannot be older than the INSERT DATE');
    END IF;
EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
  END;
/

注意:触发器不是实现此目的的唯一方法。 MATERIALIZED VIEW也可以通过CHECK CONSTRAINT强制执行此约束。替代建模也会简化事情。我将在下面详细介绍一个替代方案。

然后测试触发器:

以下是好的:

INSERT INTO INSERT_TABLE VALUES (1, TO_DATE('20170101', 'YYYYMMDD'));
INSERT INTO EXIT_TABLE VALUES (1, TO_DATE('20170501', 'YYYYMMDD'));
1 row inserted.
1 row inserted.

但是以下内容被阻止,因为退出日期在插入日期之前:

INSERT INTO INSERT_TABLE VALUES (2, TO_DATE('20170101', 'YYYYMMDD'));
INSERT INTO EXIT_TABLE VALUES (2, TO_DATE('19910501', 'YYYYMMDD'));
  

ORA-20100:退出日期不能早于INSERT DATE

这应该完成你所描述的。

我补充说,作为一个额外的考虑,替代数据模型可以帮助这样的约束。如果INSERT_DATEEXIT_DATE都是同一客户的属性,那么只有一个表的替代设计可以更简单地强制执行此操作:

CREATE TABLE INSERT_EXIT(
  CLIENT_ID NUMBER NOT NULL PRIMARY KEY,
  INSERT_DATE DATE NOT NULL,
  EXIT_DATE DATE NULL,
  CONSTRAINT EXIT_AFTER_INSERT CHECK (EXIT_DATE >= INSERT_DATE)
);

在此表中,允许以下内容:

INSERT INTO INSERT_EXIT VALUES (1,TO_DATE('20170101', 'YYYYMMDD'),NULL);
INSERT INTO INSERT_EXIT VALUES (2,TO_DATE('20170101', 'YYYYMMDD'),TO_DATE('20170501', 'YYYYMMDD'));
1 row inserted.
1 row inserted.

但以下是自然不允许的:

INSERT INTO INSERT_EXIT VALUES (3,TO_DATE('20170101', 'YYYYMMDD'),TO_DATE('19700101', 'YYYYMMDD'));
  

ORA-02290:违反检查约束(MYSCHEMA.EXIT_AFTER_INSERT)