问题
I have the table named EPOCA with this schema:
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)
);
And even though I already check if the initial date is smaller then the end date, I need to check that when I insert a new EPOCA the dates I insert will not overlap with any of the present dates.
I developed this trigger:
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;
The error I am getting when inserting is because no data was found on line 7 of the trigger and when I am updating the table the error is because the table is in mutation and the trigger cannot read the table, which makes sense but I don't know how to solve it.
Any suggestions on how to solve this problem?
回答1:
You should use the count
aggregate function in your select
query at both places as it always returns tge count evenif it is zero as follows:
...
...
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
...
...
回答2:
You don't need a SELECT
statement, but convert your code to the one such as below
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;
/
where no need to use INSERTING
case( the trigger should be BEFORE UPDATE
only ). Since the desired condition is already provided as the check constraint within the table's definition.
来源:https://stackoverflow.com/questions/65277494/oracle-sql-checking-for-overlapped-dates-using-a-trigger