检查 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 行的行级触发器是不够的。