How do I create a trigger with the below problem statement? - oracle

I am trying to create a trigger named transaction_type_af_insert that is triggered whenever a new record is inserted into ransaction_type table. This trigger will insert the new type and action into the table transaction_type_log_history after the insertion of transaction type details. The action name in the affected log table transaction_type_log_history is 'After_Insert_transaction_type'.
But facing below error:
Warning: Trigger created with compilation errors.
insert into transaction_type(id,type)values(22,'Credit Card')
*
ERROR at line 1:
ORA-04098: trigger 'P12097.TRANSACTION_TYPE_AF_INSERT' is invalid and failed
re-validation
Please help me resolve the issue
CREATE TRIGGER transaction_type_af_insert
AFTER INSERT
ON transaction_type FOR EACH ROW
DECLARE
type varchar(30)
action varchar(30)
BEGIN
UPDATE transaction_type_log_history
SET action = 'After_Insert_transaction_type'
WHERE transaction_type.id = transaction_type_log_history.id;
END;

You can query the user_errors view to see what is actually wrong; some clients let you show errors as a shortcut after you create the object (SQL Developer, SQLcl, SQL*Plus..) and see the 'Warning: Trigger created with compilation errors' message. With your current code that will say something like:
PLS-00103: Encountered the symbol "(" when expecting one of the following:
; is default authid as force under accessible
type is a reserved word so you can't use that for a local variable name - it's expecting you to be declaring a record type. Changing the name of that variable reveals the next error:
PLS-00103: Encountered the symbol "ACTION" when expecting one of the following:
:= ; not null default character
which is because you don't have semicolons after your declarations.
Fixing that still gets 'ORA-00904: "TRANSACTION_TYPE"."ID": invalid identifier' because your update statement doesn't include the transaction_type table. You can use correlation names to refer to data in the original table row statement the trigger fired against, using :new by default; so this now compiles:
CREATE OR REPLACE TRIGGER transaction_type_af_insert
AFTER INSERT ON transaction_type
FOR EACH ROW
DECLARE
l_type varchar2(30);
l_action varchar2(30);
BEGIN
UPDATE transaction_type_log_history
SET action = 'After_Insert_transaction_type'
WHERE transaction_type_log_history.id = :new.id;
END;
/
db<>fiddle
You aren't actually using either of the the two locally declared variables so you can remove those and the declare keyword.
You also seem to be trying to update the history table instead of inserting a new row there, which the problem statement seems to suggest you should be doing.

Related

Oracle SQL - Running scripts

I'm trying to create an Oracle SQL script that defines the field and triggers for multiple tables as part of my initialization for the implementation of a new project. A sample of what I'm trying to do is shown here;
ALTER TABLE TBL_SAP_VENDORS
DROP COLUMN UPT_TS;
ALTER TABLE TBL_SAP_VENDORS
ADD (
UPT_TS TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- The automatic update of fields has to be performed using a trigger
-- First we drop the trigger incase it already exists
drop trigger vendors_updt_mark;
-- Then add the trigger deffinition
CREATE TRIGGER vendors_updt_mark
before insert or update
on TBL_SAP_VENDORS
FOR EACH ROW
BEGIN
:new.UPT_TS := SYSTIMESTAMP;
END;
-- INVENTORY
ALTER TABLE TBL_SAP_INVENTORY
DROP COLUMN UPT_TS;
ALTER TABLE TBL_SAP_INVENTORY
ADD (
UPT_TS TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- The automatic update of fields has to be performed using a trigger
-- First we drop the trigger incase it already exists
drop trigger inventory_updt_mark;
-- Then add the trigger deffinition
CREATE TRIGGER inventory_updt_mark
before insert or update
on TBL_SAP_INVENTORY
FOR EACH ROW
BEGIN
:new.UPT_TS := SYSTIMESTAMP;
END;
When I try executing this in the Oracle SQL Developer I get the message :
Table TBL_SAP_VENDORS altered.
Table TBL_SAP_VENDORS altered.
Trigger VENDORS_UPDT_MARK dropped.
Trigger VENDORS_UPDT_MARK compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
6/1 PLS-00103: Encountered the symbol "ALTER"
Errors: check compiler log
When I open up the compile log I see:
Error(5,1): PLS-00103: Encountered the symbol "ALTER"
How do I run these commands, of which I have about 20 to run in a single script?
thanks
You have to end the creation of a trigger (or any PL/SQL object, for that matter), with a slash on its own line.
...
CREATE TRIGGER vendors_updt_mark
before insert or update
on TBL_SAP_VENDORS
FOR EACH ROW
BEGIN
:new.UPT_TS := SYSTIMESTAMP;
END;
/
....

Cx_oracle trigger error

I am trying to create a simple trigger in cx_oracle which copies values in a table called Student when some value is inserted in the table studentTemp. There are only two columns in each table namely stud_ID and stud_Name. When I try to insert value in StudentTemp by using
cur.execute("INSERT INTO studentTemp VALUES(1, 'Bob')")
I am getting error DatabaseError: ORA-04098: trigger 'S12345.INSERT_STUD' is invalid and failed re-validation. Following is the code
cur.execute('''CREATE OR REPLACE TRIGGER insert_Stud
AFTER INSERT ON studentTemp
FOR EACH ROW
BEGIN
INSERT INTO Student(Stud_ID,Stud_Name) VALUES
(:new.Stud_ID, :new.Stud_Name);
END;''')
I have also tried
cur.execute('''CREATE OR REPLACE TRIGGER insert_Stud
AFTER INSERT ON studentTemp
REFERENCING NEW AS new
FOR EACH ROW
BEGIN
INSERT INTO Student(Stud_ID,Stud_Name) VALUES (:new.Stud_ID, :new.Stud_Name);
END;/''')
But still get the same error
I can get it work if I use a stored procedure like this
# create insertStudent() stored procedure
cur.execute('''CREATE OR REPLACE PROCEDURE insertStudent(
sID IN STUDENT.STUDENT_ID%TYPE,
sName IN STUDENT.STUDENT_NAME%TYPE)
IS
BEGIN
INSERT INTO STUDENT VALUES(sID, sName);
END;''')
# create insert_Stud() trigger
cur.execute('''CREATE OR REPLACE TRIGGER insert_Stud
AFTER INSERT ON studentTemp
FOR EACH ROW
BEGIN
insertStudent(:new.Stud_ID, :new.Stud_Name);
END;''')
Can someone kindly tell me how to fix this. Thanks
It seems to me like you have an error in naming your Student-Table Fields.
In your Procedure, the colums are referenced as
STUDENT.STUDENT_ID
STUDENT.STUDENT_NAME
In your trigger, you call them
INSERT INTO Student(**Stud_ID**,**Stud_Name**) VALUES ...
Try using SQL*Plus to create the trigger. Then use the "show errors" command to see what the problem is. After that you should be able to use cx_Oracle without any difficulty. The only difference is that the trailing / in SQL*Plus does not need to be there.

existing state of package has been invalidated

I am facing this error.
I have two Schema Schema A and Schema B
Schema B contains a table my_table in which values are being Inserted.
There is also a triggger my_trigger written for my_table in schemaB for each row
CREATE OR REPLACE TRIGGER schemaB.my_trigger
ON schemaA.my_table
FOR EACH ROW
BEGIN
IF INSERTING THEN
schemaA.my_package.my_procedure (:NEW.field_A,NEW.field_B, :NEW.field_C);
END IF;
EXCEPTION
WHEN OTHERS THEN
Insert into my_log(DBMS_UTILITY.format_error_stack,sysdate);
END my_trigger;
/ AFTER INSERT
This trigger written on my_table of schemaB is calling a procedure which is present in Schema A.
However when the trigger is being fired I am getting the below error in my logs
ERROR: ORA-04061: existing state of package "schemaA.my_package" has been invalidated
ORA-04065: not executed, altered or dropped package "schemaA.my_package"
ORA-06508: PL/SQL: could not find program unit being called: "schemaA.my_package"
ORA-06512: at "schemaB.my_trigger", line 17 10/1/2015 6:38:07 PM
Also the procedure in schemaA is declared as PRAGMA_AUTONOMOUS_TRANSACTION
Is this some grants issue as i checked all the grants has been given, I have checked dependencies of the both trigger and procedure
and all seems to valid. Can you kindly help?
I have tried using Pragma serially_reusable in the calling package but still giving me same error
Many thanks
Possible issues you can have is:
The package/procedure you are calling is invalid
check this query whether you have an entry of your package or objects used in your package in this all_objects view
select * from all_objects where status = 'INVALID' and owner = 'SCHEMA_NAME';
Check your package is having global variables? if yes then check if those variable is not being changed by any other session
run below script to compile all the objects in your schema
begin
dbms_utility.compile_schema('SCHEMA_NAME',false);
end;
Last option if none of the above works then remove all the procedures/function from your package, add new function and try to run your function from the trigger. check if this works then your package is in special lock. after adding a new function it's state will be valid again and then you can add all your actual funcs/procs and remove the newly added one.

Oracle DB - identifier too long

I have created a connection in SQL Developer and added several tables to database. Also, I have defined some triggers. They all work well except for one that gives "identifier too long" error. I am aware of 30 character limit, but i can't see what causes this particular error. With this code, I'm trying to implement the Short-circuit keys.
Tables:
Izvestaj (IzvestajID, Datum, Opis, Tekst, PredmerID, NarucilacID, OsobaID, IzvrsilacID)
Predmer (PredmerID, Datum, Naziv, IzvrsilacID, LokacijaID)
Izvrsilac (IzvrsilacID, Naziv)
Italic values represent the primary keys of relations (tables).
Triggers:
create or replace TRIGGER "T_IZM_IZV"
AFTER UPDATE OF IZVRSILACID ON PREDMER
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'DISABLE');
UPDATE IZVESTAJ SET IZVRSILACID=:NEW.IZVRSILACID
WHERE PREDMERID=:NEW.PREDMERID;
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'ENABLE');
END;
create or replace TRIGGER "T_ZABRANA_IZM_IZV"
BEFORE UPDATE OF IzvrsilacID ON Izvestaj
FOR EACH ROW
BEGIN
RAISE_APPLICATION_ERROR(-20000, 'Direct altering of IzvrsilacID is forbidden');
END;
I have added some rows to table "Predmer" (Izvrsilac and Izvestaj also have some values inserted) and when I try to change value of column "IzvrsilacID" (foreign key), i get an error:
UPDATE "KORISNIK"."PREDMER" SET IZVRSILACID = '1' WHERE ROWID = 'AAAFBRAABAAALDxAAB' AND ORA_ROWSCN = '675526'
ORA-00972: identifier is too long
ORA-06512: at "KORISNIK.T_IZM_IZV", line 4
ORA-04088: error during execution of trigger 'KORISNIK.T_IZM_IZV'
One error saving changes to table "KORISNIK"."PREDMER":
Row 2: ORA-00972: identifier is too long
ORA-06512: at "KORISNIK.T_IZM_IZV", line 4
ORA-04088: error during execution of trigger 'KORISNIK.T_IZM_IZV'
What could cause this error? I've tried several things, even renaming triggers, tables and columns to one-letter names, but without any success.
P.S. Sorry about naming. I didn't want to translate table and column names to English because it would differ their length, which seems to cause an error in the first place.
These lines:
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'DISABLE');
EXECUTE IMMEDIATE ('ALTER TRIGGER'||'T_ZABRANA_IZM_IZV'||'ENABLE');
Should look like this:
EXECUTE IMMEDIATE ('ALTER TRIGGER '||'T_ZABRANA_IZM_IZV'||' DISABLE');
EXECUTE IMMEDIATE ('ALTER TRIGGER '||'T_ZABRANA_IZM_IZV'||' ENABLE');
Note the added spaces.
Without the spaces added, you were trying execute:
ALTER TRIGGERT_ZABRANA_IZM_IZVDISABLE
and
ALTER TRIGGERT_ZABRANA_IZM_IZVENABLE
which clearly isn't going to work.
Hope that helps.

Store the data of deleted record using trigger

I want to write a trigger which fires on deletion of a record from a table, and inserts a record in another table and uses the details of the record deleted.
Database : Oracle 10g
My trigger looked like this
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
REFERENCING NEW AS old_tab
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:old_tab.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate)
END;
here :old_tab.tabletID the tabletID is the column of the table myTable in which deletion is done.
I want to save the I and a log that it was deleted.
But when I try deleting a record I get the following error
Error code 4098, SQL state 42000: ORA-04098: trigger 'DB.MYTRIGGER' is
invalid and failed re-validation
P.S. Ran the trigger creation in NetBeans SQL Editor.
Here is the,
EDIT
STRUCTURE OF myTable (Table deletion occurs)
tabletID varchar2(15) PRIMARY KEY
tabletName varchar2(100)
STRUCTURE OF ACTIVITYLOG
username varchar2(15)
tabletKey varchar2(15)
page_ref varchar2(100)
errors varchar2(100)
remarks varchar2(100)
operationcode char(2)
lastupdateip varchar2(20)
lastupdatedate date
Sorry don't have access to SQL PLUS EDITOR.
You should use the :OLD values rather than the :NEW values. The :NEW values in a DELETE trigger (whether BEFORE or AFTER) are blank. This makes sense, because if you think about it the record has logically ceased to exist at this point.
However that is not a source of compilation errors.
"still the same error shows up on deletion. "
I suppose we could spend all day guessing what's wrong so let's stop now. You can discover the compilation errors with this simple query:
select * from user_errors
where name = 'MYTRIGGER'
and type = 'TRIGGER'
"I changed the :NEW to :OLD, and added a semicolan and ran it on SQL
PLUS, and that did the trick"
For the benefit of future here is a version of the trigger which will compile and which will correctly write the required values:
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
REFERENCING OLD AS old_tab
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:old_tab.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate);
END;
/
The problem is this:
REFERENCING NEW AS old_tab
You've redefined the NEW values with the label "old_tab". This is somewhat like adding #define FALSE TRUE to the top of a program.
Add a semicolon after the insert statement
Because you're using an AFTER DELETE trigger, you only need to access the :OLD values, e.g.:
CREATE or REPLACE TRIGGER myTrigger
AFTER DELETE
ON myTable
FOR EACH ROW
BEGIN
INSERT INTO ACTIVITYLOG values ('ADMIN',:OLD.tabletID,'MIGRATION','ERROR','TEST','T','NIL',sysdate);
END;

Resources