ORACLE SQL: After Update Trigger - sql

Problem Statement:
Create a trigger named trigger_contact_af_update that is triggered whenever the contact table is updated. This trigger will insert the org_name and action into the table contact_log_history after the update of contact details. The action name in the affected log table contact_log_history is After_Update_Contact.
The query I have at the moment is:
CREATE OR REPLACE TRIGGER trigger_contact_af_update
AFTER UPDATE ON contact
FOR EACH ROW
BEGIN
INSERT INTO contact_log_history (org_name, action) Values (:OLD.org_name, 'After_Update_Contact');
END;
But it's not working. Can someone please tell me why?
The table contact_log_history has only two columns.

Using the :OLD variable only works when using a before trigger. I would recommend you to do that in your case.
CREATE OR REPLACE TRIGGER trigger_contact_af_update
BEFORE UPDATE ON contact
FOR EACH ROW
BEGIN
INSERT INTO contact_log_history (org_name, action) Values (:old.org_name, 'After_Update_Contact');
END;

Related

trigger to update specific column when insert/update happened in same table

I trying to write a trigger that will update a column when user insert or updates a row, within the same table.
Example:
insert into user(ID, F_NM, L_NM, EMAIL) values ('1', 'John','Doe','john.doe#market.org.com');
after the insert, i want to call: update user set ORG = 'market' where ID = '1'.
create or replace trigger user_change
after insert or update of EMAIL on USER
for each row
declare
NEW_ORG VARCHAR(10);
BEGIN
CASE
when :NEW.EMAIL like '$#market.org.com' then
NEW_ORG := 'market';
........
END CASE;
UPDATE USER set ORG = NEW_ORG where ID = :NEW.ID
END;
Calculating the new ORG work, but I can't get the update statement to work.
I get 'ORA-04091 table USER is mutating, trigger/funtion may not see it', figure its due to me inserting/updating the same record at same time. Tried adding 'pragma autonomous_transaction' and 'commit' to the trigger, the insert/update of fields works but the ORG does not get updated.
Also tried changing to INSTEAD OF INSERT OR UPDATE OF EMAIL but I keep getting 'ORA-04073 column list not valid for this trigger type'
create or replace trigger user_change
instead of insert or update of EMAIL on USER
while i get 'ORA-25002 cannot create instead of triggers on tables'
create or replace trigger user_change
instead of insert on USER
Why not simply turn the trigger to a before trigger, when you can set the value before it is written? This way, you don't need to run a new DML statement on the table, which avoid the "mutating" error.
create or replace trigger user_change
after insert or update of email on user
for each row
begin
if :new.email like '%#market.org.com' then
:new.org := 'market';
end if;
end;
Looks like your org column can be calculated virtual column. In this case it would be better to create user-defined deterministic pl/sql function that returns correct calculated value and add it to your table, for example:
Alter table t add org varchar2(30) generated always as (f_get_org(email))

Before update trigger fails in oracle

I've created a trigger which should fire everey time I update the firstName of a worker in my table:
CREATE OR REPLACE TRIGGER trigger_before_update
BEFORE UPDATE ON t_workers
FOR EACH ROW
BEGIN
insert into t_logtable
values (pk_workerid , sysdate, :old.firstName)
END;
But every time I try to update a row, this is the error I got:
ora-04098 trigger is invalid and failed re-validation
What is wrong with the trigger?
And as you can see, the point would be to insert old values before update, isn't there any oracle solution, for an universial variable/column name? I mean not :old.firstName, but something, that would check any column, and gets any old value, that has been updated. It could be firstName, lastName, salary anything.
try this:
CREATE OR REPLACE TRIGGER trigger_before_update
BEFORE UPDATE ON t_workers
FOR EACH ROW
BEGIN
insert into t_logtable
values (pk_workerid , sysdate, :old.firstName);
END;
add ; after insert code

How to create mirror table in oracle by using triggers?

I've created a trigger as follows:
create or replace trigger "PASSENGERS_BACKUP_T1"
after
insert or update or delete on "PASSENGERS"
for each row
begin
if :NEW."P_ID" is NOT null then
INSERT INTO PASSENGERS_BACKUP(
PB_ID,
PB_FIRST_NAME,
PB_LAST_NAME,
PB_STREET_ADDRESS1,
PB_STREET_ADDRESS2,
PB_CITY,
PB_STATE,
PB_POSTAL_CODE,
PB_EMAIL,
PB_PHONE_NUMBER1,
PB_PHONE_NUMBER2,
PB_URL,
PB_CREDIT_LIMIT,
PB_TAGS)
VALUES (
:new.P_ID,
:new.P_FIRST_NAME,
:new.P_LAST_NAME,
:new.P_STREET_ADDRESS1,
:new.P_STREET_ADDRESS2,
:new.P_CITY,
:new.P_STATE,
:new.P_POSTAL_CODE,
:new.P_EMAIL,
:new.PHONE_NUMBER1,
:new.PHONE_NUMBER1,
:new.URL,
:new.CREDIT_LIMIT,
:new.TAGS);
end if;
end;
now, when I update​ an existing row in "passengers" table as per the above trigger another new row is getting added in "passengers_backup" table instead I would like to update the existing row whenever an update is done in "passengers" table rows. As, well If I delete a row in "Passengers" table, if that row exists in 'Passengers_backup' table it should also get deleted. How can I acheive this?
Thanks in advance.
For solving your problem you need to use trigger with corresponding SQL statement for each action: insert, update, delete. As variant you can use something like this (Note, I left only two columns from your example for readability, so modify your trigger as you need):
create or replace trigger "PASSENGERS_BACKUP_TIUD"
after insert or update or delete on "PASSENGER"
for each row
begin
if inserting then
insert into "PASSENGER_BACKUP" (pb_id, pb_first_name)
values (:NEW.pb_id, :NEW.pb_first_name);
elsif updating then
update "PASSENGER_BACKUP"
set pb_id=:NEW.pb_id, pb_first_name=:NEW.pb_first_name
where pb_id=:NEW.pb_id;
elsif deleting then
delete from "PASSENGER_BACKUP"
where pb_id=:OLD.pb_id;
end if;
end;
Also you can see work of this trigger in action on SQL Fiddle.

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

create or replace trigger "STUDENT_PERSONAL_DETAIL_T1"
AFTER insert or update or delete on "STUDENT_PERSONAL_DETAIL"
for each row
begin
insert into fa1 (s_id,name,class,sec)
select reg_no,name,class,sec
from inserted
end;
This is the trigger created using Oracle xe trigger creating interface.
It is created without error but when a insert is called on the table trigger error is shown
trigger failed -ORA-04098 is invalid and failed re-validation.
Guidance and suggestions will help a lot.
You should use:
REFERENCING new AS new
...
BEGIN
INSERT INTO fa1(s_id, name, class, sec)
VALUES (:new.reg_no, :new.name, :new.class, :new.sec);
...
see, this select statement is invalid, because there is no such table as inserted
select reg_no,name,class,sec
from inserted
EDIT if you want to log the inserted values into table fa1, you would do something like, if you had the following columns in table STUDENT_PERSONAL_DETAIL: reg_no,name,class,sec
create or replace trigger "STUDENT_PERSONAL_DETAIL_T1"
AFTER insert on "STUDENT_PERSONAL_DETAIL"
for each row
begin
insert into fa1 (s_id,name,class,sec)
values (:new.reg_no, :new.name, :new.class, :new.sec)
end;
Note the clause AFTER insert on "STUDENT_PERSONAL_DETAIL". I have omitted or update or delete to make sure this will only be triggered for newly inserted records. (because you tried to select from table 'inserted', I have concluded that's what you want to do)

Oracle Trigger on Insert or Delete or Update

Trying to create an Oracle trigger that runs after a table is updated in any way. I've been googling this all morning and came up with this:
CREATE OR REPLACE TRIGGER gb_qty_change
AFTER UPDATE OR INSERT OR DELETE ON F_ITEM_STORE
FOR EACH ROW
DECLARE
v_qty V_AD_ON_HAND%rowtype;
v_isbn TD_ITEM_DESCRIPTION.TD_IDENTIFIER%type;
BEGIN
delete from gb_transaction where gb_tide = :new.ITST_ITEM_TIDE_CODE;
select TD_IDENTIFIER INTO v_isbn from TD_ITEM_DESCRIPTION where TD_TIDE = :new.ITST_ITEM_TIDE_CODE;
select * INTO v_qty from V_AD_ON_HAND where ITST_ITEM_TIDE_CODE = :new.ITST_ITEM_TIDE_CODE;
insert into gb_transaction(gb_tide, gb_isbn, gb_used_on_hand, gb_new_on_hand)
values(:new.ITST_ITEM_TIDE_CODE, v_isbn, v_qty.USED_ON_HAND, v_qty.NEW_ON_HAND);
END;
/
I'm trying to keep it to a single record per TIDE_CODE in the new table.
V_AD_ON_HAND is a view that pulls an inventory count.
gb_transaction is my new table where I'm logging these events
Comparing it to other peoples code it looks like it should run but I'm getting "Warning: Trigger created with compilation errors."
The problem, I believe is with the :new designations for a delete trigger. There is, after all, no NEW value as the record is expunged. You can only access the :OLD values on delete.
if you section the trigger by operation, you can do this.
CREATE OR REPLACE TRIGGER gb_qty_change
AFTER UPDATE OR INSERT OR DELETE ON F_ITEM_STORE
FOR EACH ROW
DECLARE
v_qty V_AD_ON_HAND%rowtype;
v_isbn TD_ITEM_DESCRIPTION.TD_IDENTIFIER%type;
BEGIN
IF INSERTING or UPDATING then
... insert your existing code
ELSE
... do something similar with the :old values for the deleting case
end if;
END;
/
Incidentally, it is generally helpfull if you tell us WHAT the error is, not just that you had one. If compiling via SQL*Plus script, after the forward slash call to compile the trigger after the "end;" statement, add a line that says:
SHOW ERRORS TRIGGER YOUR_TRIGGER_NAME;