【问题标题】:Check for overlapped dates on any row of a table Oracle SQL检查表的任何行上的重叠日期 Oracle SQL
【发布时间】:2021-03-24 11:36:38
【问题描述】:

我有以下架构:

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 月 1 日至 6 月 1 日之间的任何时间更新现有时间段8 月 30 日。

现在我可以插入与表中任何其他日期相同的任何 EPOCA,我可以用其他 EPOCAS 的日期更新任何 EPOCA 的日期,它允许我。我可以改变什么?

【问题讨论】:

  • 检查我在问题中的答案:stackoverflow.com/questions/65277494/… 也是如此。
  • 您想将插入的数据与表中的现有数据进行比较吗?在这种情况下,您需要一个复合触发器。请注意,当您插入数据时(当然):OLD 值不存在。
  • @Popeye 感谢您的回答,在您的帮助下解决了问题!正如另一位成员告诉我的那样,这不是我错误地放弃了您的答案的问题!
  • @WernfriedDomscheit 是的,这就是我想做的,但我对复合触发器一点也不熟悉,要研究一下!

标签: sql oracle date triggers insert


【解决方案1】:

我猜你需要一个像这样的触发器:

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 子句没有给出!

否则触发器只执行当前插入/更新的行,但不与任何现有数据进行比较。

也考虑这样的情况:

在表格中,您有一个从 8 月 1 日到 30 日的期间,然后您尝试添加从 5 月 1 日到 12 月 31 日的期间。当然,这种情况也应该被触发器阻止。因此,您只需要一个语句级触发器,即仅检查插入/更新行的行级触发器是不够的。

【讨论】:

  • 非常感谢,您有什么方法可以简要解释一下您为什么使用“SELECT 1 FROM EPOCA EE”? SELECT 1 有什么作用?
  • 在exist子句中选择什么并不重要,它只是检查一行是否存在。如果您愿意,可以运行 WHERE EXISTS (SELECT 'give me five'...
  • 哦,我知道这只是为了检查 WHERE 条件是否存在!好的好的,谢谢!
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多