Oracle - 在插入之前触发不检查约束

Oracle - Trigger BEFORE INSERT not checking constraints

我有这个 table 描述了某种图书馆借书的情况:

create table emprunt (
    num_ab number(6,0) REFERENCES abonne(numero),
    num_ex number (4,0) REFERENCES exemplaire(numero),
    d_emprunt date,
    d_retour date,
    d_ret_reel date,
    nb_relance number(1,0) CHECK (nb_relance IN (1,2,3)),
    CONSTRAINT pk_emprunt PRIMARY KEY (num_ab, num_ex, d_emprunt)
);

我想创建一个触发器,当您插入新贷款时,将贷款日期设置为今天,并将 return 日期设置为今天 + 21 天。有有效的代码:

CREATE OR REPLACE TRIGGER on_insert_emprunt
BEFORE INSERT ON emprunt
FOR EACH ROW
BEGIN
    :NEW.d_emprunt := SYSDATE;
    :NEW.d_retour := SYSDATE + 21;
END;
/

但是,问题是不再检查 table emprunt 的主要约束...例如,如果我 多次 :

INSERT INTO emprunt VALUES (921102,1010,TO_DATE('29-04-2014','DD-MM-YYYY'),TO_DATE('29-04-2014','DD-MM-YYYY'),NULL,NULL);

它完美地工作...而不是说我:

UNIQUE CONSTRAINT violated

我在 table...

中有多个相同的行

PS : 抱歉法语中的 table。

SYSDATE,像所有 Oracle 日期一样,有一个时间部分。您的重复插入从触发器获得不同的时间,并且您不会看到约束冲突,除非您碰巧在彼此相隔的一秒内执行两次插入。日期不同(具体到时间级别),因此用于主键的值不同 - 因此没有违反约束。

查询可以看出主键不一样:

SELECT TO_CHAR(d_emprunt, 'YYYY-MM-DD HH24:MI:SS') AS d_emprunt,
  TO_CHAR(d_retour, 'YYYY-MM-DD HH24:MI:SS') AS d_retour
FROM emprunt
WHERE num_ab = 921102
AND num_ex = 1010;

D_EMPRUNT           D_RETOUR          
------------------- -------------------
2015-04-29 10:55:30 2015-05-20 10:55:30
2015-04-29 10:55:35 2015-05-20 10:55:35

您会看到您插入的所有记录的时间都不同。

如果您想将日期设置为午夜 you can truncate them,默认情况下会将时间组件重置为零:

CREATE OR REPLACE TRIGGER on_insert_emprunt
BEFORE INSERT ON emprunt
FOR EACH ROW
BEGIN
    :NEW.d_emprunt := TRUNC(SYSDATE);
    :NEW.d_retour := TRUNC(SYSDATE) + 21;
END;
/

顺便说一下,您的主键看起来不太有效。如果意图是阻止同一本书同时被借出两次,那就不是那么回事了。它阻止了那本书在同一天被借出,但不是在重叠的时期。所以如果我明天拿出同一本书,主键值仍然是唯一的,但范围会重叠。

主键检查

 (num_ab, num_ex, d_emprunt)

整体独一无二。

当您插入数据时 num_ab and num_ex 相同,但 d_empruntsysdate。 它正在改变。

如果您在 1 秒内插入两次数据,您将收到错误消息。