Skip to content
Advertisement

Check for overlapped dates on any row of a table Oracle SQL

I have the following schema:

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)
);

And the following trigger, that is supposed to raise an error whenever an EPOCA is inserted into the database and the period between DATA_FIM and DATA_INI is overlapped with other periods of other 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;

Think of it as: if I define the summer between june 1st and 30th of august I cannot define anyother period of the year with that period of time, nor can I update an existing period with those dates or nothing between june 1st and 30th august.

Right now I can insert any EPOCA with the same date as any other present in the table and I can update the date of any EPOCA with the dates of other EPOCAS and it allows me. What can I change?

Advertisement

Answer

I guess you would need a trigger like this one:

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;

Note, the FOR EACH ROW clause is not given!

Otherwise the trigger performs only the currently inserted/updated row but does not compare to any existing data.

Consider also cases like this:

In the table you have a period from 1st to 30th of August, then you try to add period for 1st of May to 31th of December. Of course, such situations should be also blocked by the trigger. Thus you need only a statement-level trigger, i.e. a row level trigger which checks only the inserted/updated row is not sufficient.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement