Trigger with cursor shown error : Trigger is invalid and failed re-validation - oracle

I'm trying to create Oracle after insert trigger with the following code:
CREATE OR REPLACE TRIGGER AutoManhour
AFTER INSERT ON TBL_MSTPROJECT
FOR EACH ROW
DECLARE
CURSOR c_Section IS
SELECT IDSECTION AS IDSECTION FROM TBL_MSTSECTIONHR;
v_Section c_Section%ROWTYPE;
BEGIN
OPEN c_Section;
LOOP
FETCH c_Section INTO v_Section;
INSERT INTO TBL_TRXMANHOURS (ID_SECTION,INPUTBY_TRXMANHOURS,INPUTON_TRXMANHOURS,ID_PROJECT)
VALUES (v_Section.IDSECTION,'IT_ROBOT',SYSDATE,:new.IDPROJECT);
END LOOP;
CLOSE c_Section;
END AutoManhour;
/
But it retrieve an error :
ORA-04098: trigger 'DEPEEL.AUTOMANHOUR' is invalid and failed
re-validation
Why does this happen?

I think you must have used the incorrect column/table names or incorrect datatypes are used while inserting data into TBL_TRXMANHOURS. And of course, there is an infinite loop, You should make some condition to make it finite
Oracle will try to recompile invalid objects as they are referred to. Here the trigger is invalid
select * from user_errors where type = 'TRIGGER' and name = 'AUTOMANHOUR'
You can try the above query to find the actual error.
Cheers!!

Related

SQL Error: ORA-04091 while executing Trigger

I am trying to execute my trigger:
CREATE OR REPLACE TRIGGER Trg_video_bfr_delete
AFTER DELETE ON CMS_VIDEO
FOR EACH ROW
DECLARE
CODE varchar2(60);
BEGIN
SELECT CODE INTO CODE
from CMS_VIDEO
WHERE CODE = :OLD.CODE;
IF CODE IS NOT NULL THEN
INSERT INTO ASSET_DELETE_INDEX(CODE,ASSET_TYPE,IW_VPATH,LANGUAGE,MODIFIED_DTE)
VALUES (CODE,'Video',:old.IW_VPATH,:old.CONTENT_LANGUAGE,sysdate);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO ASSET_DELETE_INDEX (CODE,ASSET_TYPE,IW_VPATH,LANGUAGE,MODIFIED_DTE)
VALUES (CODE,'Video',null,:old.CONTENT_LANGUAGE,sysdate);
COMMIT;
END Trg_video_bfr_delete;
/
But I am getting the following error while executing a delete command on the table
Error report -
SQL Error: ORA-04091: table LSDS.CMS_VIDEO is mutating, trigger/function may not see it
ORA-06512: at "LSDS.TRG_VIDEO_BFR_DELETE", line 6
ORA-04088: error during execution of trigger 'LSDS.TRG_VIDEO_BFR_DELETE'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
Could anyone please help?
You have written trigger AFTER DELETE ON CMS_VIDEO. This trigger will fire when DELETE is performed from CMS_VIDEO table. So when CMS_VIDEO table is being modified, you cannot modify or query the same table in any of your triggers, procedures or functions.
CREATE OR REPLACE TRIGGER Trg_video_bfr_delete
AFTER DELETE ON CMS_VIDEO
FOR EACH ROW
BEGIN
IF :old.CODE IS NOT NULL THEN
INSERT INTO ASSET_DELETE_INDEX(CODE, ASSET_TYPE, IW_VPATH, LANGUAGE, MODIFIED_DTE)
VALUES (:old.CODE, 'Video', :old.IW_VPATH, :old.CONTENT_LANGUAGE, sysdate);
END IF;
END Trg_video_bfr_delete;
/
This is because you are deleting record from table and same table is used as reference inside trigger. This is case of "Mutating Error". You should switch to statement level trigger is it fits your requirement or you can use compound trigger which has multiple entry point and are capable of handling such scenarios.
Please refer https://oracle-base.com/articles/9i/mutating-table-exceptions
As per the snippet provided, I dont see any point in doing a SELECT on mutating TABLE.
We can easily ise :OLD.CODE to fetch the value. Hope below snippet helps.
CREATE OR REPLACE TRIGGER Trg_video_bfr_delete AFTER
DELETE ON CMS_VIDEO FOR EACH ROW
-- DECLARE CODE VARCHAR2(60);
BEGIN
-- SELECT CODE INTO CODE FROM CMS_VIDEO WHERE CODE = :OLD.CODE;
IF CODE IS NOT NULL THEN
INSERT
INTO ASSET_DELETE_INDEX
(
CODE,
ASSET_TYPE,
IW_VPATH,
LANGUAGE,
MODIFIED_DTE
)
VALUES
(
:old.code,
'Video',
:old.IW_VPATH,
:old.CONTENT_LANGUAGE,
sysdate
);
END IF;
EXCEPTION
WHEN OTHERS THEN
INSERT
INTO ASSET_DELETE_INDEX
(
CODE,
ASSET_TYPE,
IW_VPATH,
LANGUAGE,
MODIFIED_DTE
)
VALUES
(
:old.code,
'Video',
NULL,
:old.CONTENT_LANGUAGE,
sysdate
);
COMMIT;
END Trg_video_bfr_delete;

PL/SQL Invalid Identifier

While creating a trigger on the 'emprunter' table, I'm trying to compare a value coming from another table 'exemplaire.numexemplaire' which is supposed to be an INTEGER. But I keep getting the same errors which is:
Error(4,7): PL/SQL: SQL Statement ignored
Error(7,15): PL/SQL: ORA-00904: "EMPRUNTER"."NUMEXEMPLAIRE":
invalid identifier
How can I do to retrieve the value of a field coming from another table (exemplaire.numexemplaire)?
CREATE OR REPLACE TRIGGER BIEmprunter
BEFORE INSERT OR UPDATE OF numexemplaire ON emprunter
FOR EACH ROW
DECLARE
livreEmpruntable INTEGER;
BEGIN
SELECT exemplaire.empruntable
INTO livreEmpruntable
FROM exemplaire
WHERE emprunter.numexemplaire = exemplaire.numexemplaire;
IF livreEmpruntable != 1 THEN
raise_application_error(-20000, 'exemplaire non empruntable');
END if;
END;
UPDATE 1
Thanks for the answer but I keep getting this error whule trying to test the trigger...
SQL Error: ORA-04098: trigger 'EQUIPE10.ABONNEMENTPASAJOUR' is invalid and failed re-validation
04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation"
*Cause: A trigger was attempted to be retrieved for execution and was
found to be invalid. This also means that compilation/authorization
failed for the trigger.
*Action: Options are to resolve the compilation/authorization errors,
disable the trigger, or drop the trigger.
Update 2
Thanks again for the answer, the trigger can compile now. But when now I'm trying to make it work when inserting value but I keep getting the error because there is no data yet...
INSERT INTO emprunter
VALUES (2, 1, 18, '17-02-01', null);
Error report -
SQL Error: ORA-01403: no data found
ORA-06512: at "EQUIPE10.BIEMPRUNTER", line 4
ORA-04088: error during execution of trigger 'EQUIPE10.BIEMPRUNTER'
01403. 00000 - "no data found"
*Cause: No data was found from the objects.
*Action: There was no data from the objects which may be due to end of fetch.
You want to join the two tables:
CREATE OR REPLACE TRIGGER BIEmprunter
BEFORE INSERT OR UPDATE OF numexemplaire ON emprunter
FOR EACH ROW
DECLARE
livreEmpruntable INTEGER;
BEGIN
SELECT exemplaire.empruntable
INTO livreEmpruntable
FROM exemplaire
join emprunter
ON emprunter.numexemplaire = exemplaire.numexemplaire;
IF livreEmpruntable != 1 THEN
raise_application_error(-20000, 'exemplaire non empruntable');
END if;
END;
Also, the above join query can potentially return multiple rows and the call will result in exception (uncaught as of now)
ORA-01422: exact fetch returns more than requested number of rows
I guess you want to use :new to access the record that triggered the trigger:
CREATE OR REPLACE TRIGGER BIEmprunter
BEFORE INSERT OR UPDATE OF numexemplaire ON emprunter
FOR EACH ROW
DECLARE
livreEmpruntable INTEGER;
BEGIN
SELECT exemplaire.empruntable
INTO livreEmpruntable
FROM exemplaire
WHERE :new.numexemplaire = exemplaire.numexemplaire;
IF livreEmpruntable != 1 THEN
raise_application_error(-20000, 'exemplaire non empruntable');
END if;
END;

Oracle After Update Trigger error

I want to keep track of changes to one table in another table. What I need is an after update trigger which writes the name of changed column (if multiple columns are changed then there will be multiple inserts to the CHANGES table),the column's old and new values. How do I do that. I tried this but got an error after updating the table.So I'm giving you just the body.
IF :NEW.STAJYEAR!=:OLD.STAJYEAR THEN
INSERT INTO X_STAJ (USERID,EDITDATE,CHANGEDCOLUMN,OLDVALUE,NEWVALUE)
VALUES (:NEW.USERID,SYSDATE,'STAJYEAR',:OLD.STAJYEAR,:NEW.STAJYEAR);
END IF;
the error code is :ORA-04098: trigger 'SYS.TR__TRACK_CHANGES' is invalid and failed re-validation
CREATE OR REPLACE TRIGGER STAJCHANGER.TR_TRACK_CHANGES
AFTER UPDATE
OF STAJYEAR
,STAJMONTH
,STAJDAY
ON STAJCHANGER.STAJ
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
OLDVALUE NUMBER;
NEWVALUE NUMBER;
COLUMNID NUMBER;
BEGIN
IF :NEW.STAJYEAR!=:OLD.STAJYEAR THEN
INSERT INTO X_STAJ (USERID,EDITDATE,CHANGEDCOLUMN,OLDVALUE,NEWVALUE)
VALUES (:NEW.USERID,SYSDATE,'STAJYEAR',:OLD.STAJYEAR,:NEW.STAJYEAR);
END IF;
IF :NEW.STAJMONTH!=:OLD.STAJMONTH THEN
INSERT INTO X_STAJ (USERID,EDITDATE,CHANGEDCOLUMN,OLDVALUE,NEWVALUE)
VALUES (:NEW.USERID,SYSDATE,'STAJMONTH',:OLD.STAJMONTH,:NEW.STAJMONTH);
END IF;
IF :NEW.STAJDAY!=:OLD.STAJDAY THEN
INSERT INTO X_STAJ (USERID,EDITDATE,CHANGEDCOLUMN,OLDVALUE,NEWVALUE)
VALUES (:NEW.USERID,SYSDATE,'STAJDAY',:OLD.STAJDAY,:NEW.STAJDAY);
END IF;
END TR_TRACK_CHANGES;
/
The error appears to indicates that the trigger owner is SYS, but the creation statement you show explicitly gives the owner as STAJCHANGER.
This makes me wonder, did you accidentally create an (invalid) version of the trigger in SYS at some point, and forget to drop it?
This SQL Plus command will show the error:
SHOW ERROR TRIGGER STAJCHANGER.TR_TRACK_CHANGES

compile error when creating an "instead of" trigger for a view

I've created an "instead of" trigger for a simple view that only does select * on a table and a trigger that does nothing (I wanted to minimize the problem):
create or replace view tmp(id, nazwa, nip, adres, zalega, punkty) as
select * from klient
create or replace trigger tmp_trg
instead of insert
on tmp
for each row
begin
end;
The view is created.
Then when I want do declare this trigger sql developer returns error:
Error(8,1): PLS-00103: Encountered the symbol "END" when expecting one of the following: begin case declare exit for goto if loop mod null pragma raise return select update while with 'an identifier' 'a double-quoted delimited-identifier' 'a bind variable' << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe
just add "null;" between the begin and the end.
a trigger that does nothing (I wanted to minimize the problem):
I'm not sure I understand why you need a trigger if it does nothing ?
To answer, there isn't a valid PL/SQL statement in your trigger code block, add a NULL to make it a valid block and have no action.
create or replace trigger tmp_trg
instead of insert
on tmp
for each row
begin
NULL;
end;

if insert error in oracle trigger creation?

CREATE TRIGGER Background_Process_Report_trit
AFTER INSERT
ON Background_Process_Report
FOR EACH ROW
IF INSERT(PROCESS_NAME)
BEGIN
SET EXECUTION_TIMESTAMP := NEW.TIMESTAMP;
END;
/
process_name -- column in my Background_Process_Report table.but i want to update the each time the process_name is created(by java application), trigger update the time in the EXECUTION_TIMESTAMP table.
but it is throwing the compliation error..
error:
IF INSERT(PROCESS_NAME)
*
ERROR at line 5:
ORA-04079: invalid trigger specification
how to reslove this error
If EXECUTION_TIMESTAMP is a table as you say, then it must have a column you want to update, let's call it TIMESTAMP_COL. The the trigger would be something like:
CREATE TRIGGER Background_Process_Report_trit
AFTER INSERT
ON Background_Process_Report
FOR EACH ROW
WHEN (NEW.PROCESS_NAME IS NOT NULL)
BEGIN
UPDATE EXECUTION_TIMESTAMP
SET TIMESTAMP_COL = NEW.TIMESTAMP
WHERE ???; -- Change ??? to the appropriate condition
END;
/
I have assumed that by "IF INSERT(PROCESS_NAME)" you mean "if a non-null value is inserted into PROCESS_NAME" and created a WHEN clause to match.

Resources