已编辑,其中包含 FOREIGN KEY 防止孤儿 CLIENT_IDs 的信息。
要生成执行您所描述的规则的触发器,以下方法将起作用。
首先,创建一些测试表:
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 和EXIT_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)