ORA-04098 is invalid and failed re-validation - sql

I wrote the below trigger and it was compiled successfully.
create or replace trigger after_update_datetable
after update on date_table
for each row
begin
if(TRUNC(:new.end_date) - TRUNC(:new.start_date) > 90) THEN
UPDATE date_table set END_DATE = :old.END_DATE, START_DATE = :old.START_DATE;
END IF;
END;
However when I performed the below update statement I got this error
update date_table set end_date = sysdate, start_date = sysdate-100;
trigger failed -ORA-04098 is invalid and failed re-validation.
Any help is appreciated. Thanks

you are updating the same table from the trigger, that is not allowed :
if(TRUNC(:new.end_date) - TRUNC(:new.start_date) > 90) THEN
UPDATE date_table set END_DATE = :old.END_DATE, START_DATE = :old.START_DATE;
END IF;
you better use a trigger for BEFORE instead of AFTER, and update the values of the record :NEW
see this answer, it will be useful for you

Related

how to convert a mutating trigger to a stored procedure

I have the following trigger:
CREATE OR REPLACE TRIGGER planning_trig BEFORE
UPDATE OF planned_remediation_date ON evergreen
FOR EACH ROW
DECLARE
planned_remediation_date DATE;
BEGIN
SELECT
planned_remediation_date
INTO planned_remediation_date
FROM
evergreen
WHERE
hostname = :new.hostname
AND instance_name = :new.instance_name
AND product_home = :new.product_home
AND it_service = :new.it_service
AND sw_name = :new.sw_name;
IF
planned_remediation_date IS NOT NULL
AND planned_remediation_date > trunc(sysdate)
THEN
UPDATE evergreen
SET
planning_status = 'planned';
ELSE
UPDATE evergreen
SET
planning_status = 'overdue';
END IF;
END;
/
After an update of the row in my table evergreen I get this error:
ORA-04091: table PTR.EVERGREEN is mutating, trigger/function may not see it
I believe the error comes from the fact that I'm trying to update the very same table the trigger is firing on. I read that the best way to handle updates in the same table are stored procedures but I'm quite new to oracle and don't know how to achieve that. Another possibility I heard is AUTONOMOUS_TRANSACTION Pragma but not sure either if this applies to my case.
A little more background, the underlying table has a composite unique key (hostname,instance_name,product_home,it_service,sw_name) and I want to update an existing column on this table called planning_status based on the updated value of planned_remediation_date. If that value is not null and greater then today then update with planned else overdue.
Expression planned_remediation_date IS NOT NULL is redundant. planned_remediation_date > trunc(sysdate) is never TRUE when planned_remediation_date is NULL.
Your trigger can be written much shorter:
CREATE OR REPLACE TRIGGER planning_trig
BEFORE UPDATE OF planned_remediation_date ON evergreen
FOR EACH ROW
BEGIN
IF :new.planned_remediation_date > trunc(sysdate) THEN
:new.planning_status := 'planned';
ELSE
:new.planning_status := 'overdue';
END IF;
END;
/
I guess you like to modify the updated row, not other rows in that table. Otherwise you would need a procedure or a COMPOUND trigger

Compare Date with Trigger on Oracle SQL

I have a table with those columns:
DateDebVal DATE
DateFinVal DATE
isCurrent NUMBER
And I need to have a trigger that do something like this:
CREATE TRIGGER check_date
AFTER INSERT OR UPDATE ON tablename
FOR EACH ROW
BEGIN
IF sysdate < DateFinVal
set isCurrent = 1
ELSE
set isCurrent = 0
END;
Can I compare those dates? Is it a good idea to use a trigger instead of a view or a procedure?
Dates can absolutely be compared, but assignment is done using := in PL/SQL (not with set)
If you want to change the value of a newly inserted row, you have to use a BEFORE trigger:
CREATE TRIGGER check_date
BEFORE INSERT OR UPDATE ON tablename
FOR EACH ROW
BEGIN
IF sysdate < :new.datefinval
:new.iscurrent := 1;
ELSE
:new.iscurrent := 0;
END IF;
END;
/
Online example: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=796347f1b5811448dddf2d0a532c2c2c
Sysdate and DateFinVal are of DATE type so you would compare those. It depends what for you need this trigger.

Check future date in trigger

I want to launch a trigger if a user try to replace current date with a future date.But subquery might not allowed in trigger. How can i solve this issue? Any suggestion....
CREATE OR REPLACE TRIGGER check_join_date
BEFORE UPDATE OF join_date ON DOCTOR
FOR EACH ROW
WHEN (NEW.join_date > (SELECT CURRENT_DATE+1 FROM DUAL) )
BEGIN
RAISE_APPLICATION_ERROR(-20509,'Do not Enter Future Date..');
END check_join_date;
/
I am getting this error after running this code in Oracle.
ORA-02251: subquery not allowed here
test this
CREATE OR REPLACE TRIGGER check_join_date
BEFORE UPDATE OF join_date ON DOCTOR
FOR EACH ROW
WHEN (NEW.join_date > CURRENT_DATE+1)
BEGIN
RAISE_APPLICATION_ERROR(-20509,'Do not Enter Future Date..');
END check_join_date;
/

Oracle update trigger issue

Question is I have the following trigger to watch my specific column "CHANGED" if its updated to a 1 I would like it to update the same row and the column "CHANGED_DATE" to the current SYSDATE. For some reason I keep getting this error any help would be greatly appreciated.
Error
UPDATE "SYSADM"."SHIP_CALENDAR" SET CHANGED = '1' WHERE ROWID = 'AABCxCAAEAAAKYEAAB' AND ORA_ROWSCN = '6165377066'
ORA-04091: table SYSADM.SHIP_CALENDAR is mutating, trigger/function may not see it
ORA-06512: at "SYSADM.SHIP_CALENDAR_CHANGED", line 5
ORA-04088: error during execution of trigger 'SYSADM.SHIP_CALENDAR_CHANGED'
Trigger
create or replace TRIGGER SHIP_CALENDAR_CHANGED
AFTER UPDATE
OF CHANGED
ON SHIP_CALENDAR
REFERENCING OLD AS o NEW AS n
FOR EACH ROW
DECLARE
BEGIN
-- UPDATE SHIP CALENDAR SET UPDATE_CHANGE TO SYSDATE IF CHANGED CHANGES
IF :n.CHANGED = '1' then
UPDATE SHIP_CALENDAR
SET CHANGED_DATE = SYSDATE
WHERE SHIPMENT_ID = :o.SHIPMENT_ID;
END IF;
END;
Table
Use a before update trigger:
create or replace TRIGGER SHIP_CALENDAR_CHANGED
BEFORE UPDATE
OF CHANGED
ON SHIP_CALENDAR
REFERENCING OLD AS o NEW AS n
FOR EACH ROW
DECLARE
BEGIN
-- UPDATE SHIP CALENDAR SET UPDATE_CHANGE TO SYSDATE IF CHANGED CHANGES
IF :n.CHANGED = '1' then
:n.CHANGED_DATE := SYSDATE
END IF;
END;

How to user trigger to update a column comparing with system date in Oracle?

I wrote this trigger to update a certain column. The trigger I wrote is this:
CREATE TRIGGER updateotMark
BEFORE UPDATE
ON sBookBorrow
FOR EACH ROW
WHEN(SYSDATE-to_date(etime)>15)
BEGIN
UPDATE otMark = 1;
END;
/
This is the first time I use trigger, so I have no idea what went wrong. Any ideas? Thanks everyone for your answer.
UPDATE: This is what I got in the console. What did I do wrong?
UPDATE2:Now it has a error message:ERROR at line 5:
ORA-04076: invalid NEW or OLD specification
What is the data type of "etime"?
If date, you don't need to use "TO_DATE" function. ex.(SYSDATE - etime > 15)
If VARCHAR2, you need to put the format. ex. TO_DATE(etime,'YYYYMMDD')
However, use SHOW in SQLPlus will give you more information about error.
SHOW ERROR TRIGGER updateotMark;
Let try this.
CREATE OR REPLACE TRIGGER updateotMark
BEFORE UPDATE
ON sBookBorrow
FOR EACH ROW
WHEN (SYSDATE - NEW.etime > 15)
BEGIN
:NEW.otmark := 1;
END;
Just update the :new value
CREATE TRIGGER updateotMark
BEFORE UPDATE
ON sBookBorrow
FOR EACH ROW
WHEN(SYSDATE-to_date(etime)>15)
BEGIN
:new.otmark = 1;
END;