Oracle SQL 使用触发器检查重叠日期
Oracle SQL checking for overlapped dates using a trigger
我有 table 名为 EPOCA 的架构:
CREATE TABLE EPOCA
(
ID INT
CONSTRAINT PK_EPOCA PRIMARY KEY,
NOME VARCHAR(250),
DATE_INITIAL DATE
CONSTRAINT NN_EPOCA_DATA_INI NOT NULL,
DATE_END DATE,
CONSTRAINT CK_EPOCA_DATAS CHECK (DATE_INITIAL < DATE_END)
);
即使我已经检查了初始日期是否小于结束日期,我仍需要检查当我插入一个新的 EPOCA 时,我插入的日期不会与任何当前日期重叠。
我开发了这个触发器:
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
BEFORE INSERT OR UPDATE
ON EPOCA
FOR EACH ROW
DECLARE
FLAG_DATE NUMBER;
BEGIN
FLAG_DATE := 0;
IF INSERTING THEN
SELECT E.ID INTO FLAG_DATE FROM EPOCA E WHERE E.DATE_INITIAL < :NEW.DATE_INITIAL AND E.DATE_END > :NEW.DATE_END;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2098, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
ELSIF UPDATING THEN
SELECT E.ID INTO FLAG_DATE FROM EPOCA E WHERE E.DATE_INITIAL < :NEW.DATE_INITIAL AND E.DATA_END > :NEW.DATA_END;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2099, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
我在插入时遇到的错误是因为在触发器的第 7 行没有找到数据,而当我更新 table 时出现错误是因为 table 处于突变状态并且trigger cannot read the table,这是有道理的,但我不知道如何解决它。
关于如何解决这个问题有什么建议吗?
您不需要 SELECT
语句,但将您的代码转换为如下所示的代码
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
BEFORE UPDATE
ON EPOCA
FOR EACH ROW
DECLARE
FLAG_DATE NUMBER;
BEGIN
FLAG_DATE := 0;
IF UPDATING THEN
IF :OLD.DATE_INITIAL < :NEW.DATE_INITIAL AND :OLD.DATE_END > :NEW.DATE_END THEN
FLAG_DATE := :OLD.ID;
END IF;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2099, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
/
无需使用 INSERTING
大小写(触发器应仅 BEFORE UPDATE
)。由于所需条件已作为 table 定义中的检查约束提供。
您应该在 select
查询中的两个地方都使用 count
聚合函数,因为它总是 returns tge 计数,即使它为零,如下所示:
...
...
SELECT count(*) INTO FLAG_DATE FROM EPOCA E WHERE E.DATA_INI < :NEW.DATA_INI AND E.DATA_FIM > :NEW.DATA_FIM;
IF FLAG_DATE <> 0 THEN
...
...
我有 table 名为 EPOCA 的架构:
CREATE TABLE EPOCA
(
ID INT
CONSTRAINT PK_EPOCA PRIMARY KEY,
NOME VARCHAR(250),
DATE_INITIAL DATE
CONSTRAINT NN_EPOCA_DATA_INI NOT NULL,
DATE_END DATE,
CONSTRAINT CK_EPOCA_DATAS CHECK (DATE_INITIAL < DATE_END)
);
即使我已经检查了初始日期是否小于结束日期,我仍需要检查当我插入一个新的 EPOCA 时,我插入的日期不会与任何当前日期重叠。
我开发了这个触发器:
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
BEFORE INSERT OR UPDATE
ON EPOCA
FOR EACH ROW
DECLARE
FLAG_DATE NUMBER;
BEGIN
FLAG_DATE := 0;
IF INSERTING THEN
SELECT E.ID INTO FLAG_DATE FROM EPOCA E WHERE E.DATE_INITIAL < :NEW.DATE_INITIAL AND E.DATE_END > :NEW.DATE_END;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2098, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
ELSIF UPDATING THEN
SELECT E.ID INTO FLAG_DATE FROM EPOCA E WHERE E.DATE_INITIAL < :NEW.DATE_INITIAL AND E.DATA_END > :NEW.DATA_END;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2099, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
我在插入时遇到的错误是因为在触发器的第 7 行没有找到数据,而当我更新 table 时出现错误是因为 table 处于突变状态并且trigger cannot read the table,这是有道理的,但我不知道如何解决它。
关于如何解决这个问题有什么建议吗?
您不需要 SELECT
语句,但将您的代码转换为如下所示的代码
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
BEFORE UPDATE
ON EPOCA
FOR EACH ROW
DECLARE
FLAG_DATE NUMBER;
BEGIN
FLAG_DATE := 0;
IF UPDATING THEN
IF :OLD.DATE_INITIAL < :NEW.DATE_INITIAL AND :OLD.DATE_END > :NEW.DATE_END THEN
FLAG_DATE := :OLD.ID;
END IF;
IF FLAG_DATE <> 0 THEN
RAISE_APPLICATION_ERROR(-2099, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
/
无需使用 INSERTING
大小写(触发器应仅 BEFORE UPDATE
)。由于所需条件已作为 table 定义中的检查约束提供。
您应该在 select
查询中的两个地方都使用 count
聚合函数,因为它总是 returns tge 计数,即使它为零,如下所示:
...
...
SELECT count(*) INTO FLAG_DATE FROM EPOCA E WHERE E.DATA_INI < :NEW.DATA_INI AND E.DATA_FIM > :NEW.DATA_FIM;
IF FLAG_DATE <> 0 THEN
...
...