检查 table Oracle SQL 的任何行上的重叠日期
Check for overlapped dates on any row of a table Oracle SQL
我有以下架构:
CREATE TABLE EPOCA
(
ID INT
CONSTRAINT PK_EPOCA PRIMARY KEY,
NOME VARCHAR(250),
DATA_INI DATE
CONSTRAINT NN_EPOCA_DATA_INI NOT NULL,
DATA_FIM DATE,
CONSTRAINT CK_EPOCA_DATAS CHECK (DATA_INI < DATA_FIM)
);
以及以下触发器,每当将 EPOCA 插入数据库并且 DATA_FIM 和 DATA_INI 之间的时间段与其他 EPOCAS 的其他时间段重叠时,应该会引发错误。
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
AFTER INSERT OR UPDATE
ON EPOCA
FOR EACH ROW
BEGIN
IF INSERTING THEN
IF :OLD.DATA_INI <= :NEW.DATA_INI AND :OLD.DATA_FIM >= :NEW.DATA_FIM THEN
RAISE_APPLICATION_ERROR(-20021, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
ELSIF UPDATING THEN
IF :OLD.DATA_INI <= :NEW.DATA_INI AND :OLD.DATA_FIM >= :NEW.DATA_FIM THEN
RAISE_APPLICATION_ERROR(-20022, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
可以这样想:如果我在 6 月 1 日到 8 月 30 日之间定义夏季,我就不能用那个时间段定义一年中的任何其他时间段,也不能用这些日期更新现有时间段,或者在 6 月之间什么都没有8 月 1 日和 30 日。
现在我可以插入与 table 中存在的任何其他日期相同的任何 EPOCA,并且我可以使用其他 EPOCAS 的日期更新任何 EPOCA 的日期,这允许我。我可以改变什么?
我猜你需要这样的触发器:
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
AFTER INSERT OR UPDATE
ON EPOCA
c INTEGER;
BEGIN
SELECT COUNT(*)
INTO c
FROM EPOCA e
WHERE EXISTS (
SELECT 1
FROM EPOCA ee
WHERE (e.DATA_INI BETWEEN ee.DATA_INI AND ee.DATA_FIM
OR e.DATA_FIM BETWEEN ee.DATA_INI AND ee.DATA_FIM)
AND ee.ROWID <> e.ROWID);
IF c > 0 THEN
RAISE_APPLICATION_ERROR(-20021, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END;
注意,没有给出FOR EACH ROW
子句!
否则触发器仅执行当前 inserted/updated 行,但不与任何现有数据进行比较。
还要考虑这样的情况:
在 table 中,您有一个从 8 月 1 日到 30 日的期间,然后您尝试添加 5 月 1 日到 12 月 31 日的期间。当然,这种情况也应该被扳机挡住。因此,您只需要一个语句级触发器,即仅检查 inserted/updated 行的行级触发器是不够的。
我有以下架构:
CREATE TABLE EPOCA
(
ID INT
CONSTRAINT PK_EPOCA PRIMARY KEY,
NOME VARCHAR(250),
DATA_INI DATE
CONSTRAINT NN_EPOCA_DATA_INI NOT NULL,
DATA_FIM DATE,
CONSTRAINT CK_EPOCA_DATAS CHECK (DATA_INI < DATA_FIM)
);
以及以下触发器,每当将 EPOCA 插入数据库并且 DATA_FIM 和 DATA_INI 之间的时间段与其他 EPOCAS 的其他时间段重叠时,应该会引发错误。
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
AFTER INSERT OR UPDATE
ON EPOCA
FOR EACH ROW
BEGIN
IF INSERTING THEN
IF :OLD.DATA_INI <= :NEW.DATA_INI AND :OLD.DATA_FIM >= :NEW.DATA_FIM THEN
RAISE_APPLICATION_ERROR(-20021, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
ELSIF UPDATING THEN
IF :OLD.DATA_INI <= :NEW.DATA_INI AND :OLD.DATA_FIM >= :NEW.DATA_FIM THEN
RAISE_APPLICATION_ERROR(-20022, 'UPDATE FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END IF;
END;
可以这样想:如果我在 6 月 1 日到 8 月 30 日之间定义夏季,我就不能用那个时间段定义一年中的任何其他时间段,也不能用这些日期更新现有时间段,或者在 6 月之间什么都没有8 月 1 日和 30 日。
现在我可以插入与 table 中存在的任何其他日期相同的任何 EPOCA,并且我可以使用其他 EPOCAS 的日期更新任何 EPOCA 的日期,这允许我。我可以改变什么?
我猜你需要这样的触发器:
CREATE OR REPLACE TRIGGER TRGEPOCASNAOSOBREPOSTAS
AFTER INSERT OR UPDATE
ON EPOCA
c INTEGER;
BEGIN
SELECT COUNT(*)
INTO c
FROM EPOCA e
WHERE EXISTS (
SELECT 1
FROM EPOCA ee
WHERE (e.DATA_INI BETWEEN ee.DATA_INI AND ee.DATA_FIM
OR e.DATA_FIM BETWEEN ee.DATA_INI AND ee.DATA_FIM)
AND ee.ROWID <> e.ROWID);
IF c > 0 THEN
RAISE_APPLICATION_ERROR(-20021, 'INSERT FAILED BECAUSE SELECTED DATES OVERLAP EXISTENT ONES');
END IF;
END;
注意,没有给出FOR EACH ROW
子句!
否则触发器仅执行当前 inserted/updated 行,但不与任何现有数据进行比较。
还要考虑这样的情况:
在 table 中,您有一个从 8 月 1 日到 30 日的期间,然后您尝试添加 5 月 1 日到 12 月 31 日的期间。当然,这种情况也应该被扳机挡住。因此,您只需要一个语句级触发器,即仅检查 inserted/updated 行的行级触发器是不够的。