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_emprunt
为 sysdate
。
它正在改变。
如果您在 1 秒内插入两次数据,您将收到错误消息。
我有这个 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_emprunt
为 sysdate
。
它正在改变。
如果您在 1 秒内插入两次数据,您将收到错误消息。