How to Exclude DB Column in a Trigger Function (Oracle) - oracle

I have created a very simple trigger in a certain table (e.g. TABLE_TRIGGER) that will call a procedure (handles all the logic). This table has a column (e.g. AUDITID) which I would like to exclude in the trigger function, I mean, if update is only done in AUDITID column, the procedure should not be executed.
Below is the trigger:
CREATE OR REPLACE TRIGGER TABLE_TRIGGER_FUNCTION
AFTER INSERT OR UPDATE
ON TABLE_TRIGGER
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
-- procedure();
END;
Is there other way to do it, other than the one suggested here: Oracle: excluding updates of one column for firing a trigger
The answer provided here is the one I would like to have Fire trigger on updates (excluding certain fields change) but I am not sure if this is something that can also be done using Oracle PL/SQL syntax.
By the way, I have tried using the following WHEN statement by excluding the AUDITID column but the trigger did not work at all and the procedure was not executed.
WHEN (NEW.FILEID != OLD.FILEID OR
NEW.DESCRIPTION != OLD.DESCRIPTION OR
NEW.IMAGEID != OLD.IMAGEID OR
NEW.STATETYPEID != OLD.STATETYPEID OR
NEW.ACCESSLEVELID != OLD.ACCESSLEVELID OR
NEW.FILETYPEID != OLD.FILETYPEID)

I'm not aware of a way to exclude a column from an update trigger, but you could define a list of columns it would fire on, and list all the columns except the auditid:
CREATE OR REPLACE TRIGGER TABLE_TRIGGER_FUNCTION
AFTER INSERT OR UPDATE
OF FILEID, -- Field list starts here...
DESCRIPTION,
IMAGEID,
STATETYPEID,
ACCESSLEVELID,
ACCESSLEVELID,
FILETYPEID -- ... and ends here
ON TABLE_TRIGGER
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
-- procedure();
END;

During insets ,all the references to OLD for insert event will result in NULL hence your procedure is not gonna run.
Consider and refer the below code blocks:
I think this is something you are looking for.
create table hr.test(id1 int,id2 int);
create or replace procedure hr.test_proc
as
begin
dbms_output.put_line('trigger');
end;
CREATE OR REPLACE TRIGGER test_trg
AFTER INSERT OR UPDATE
ON hr.test
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
if updating and :old.id1 !=:new.id1 then
null;--do nothing just as you want
else
hr.test_proc;--call your proc
end if;
END;

Related

ORACLE - After trigger is not passing the value to the procedure

I have a problem with a "after insert" trigger which won't pass the value to a stored procedure that i'm calling inside the trigger.
It works ok for update and also i should mention that i am querying the table in the procedure that i am calling.
It goes something like:
create or replace trigger test_trg
after insert or update on table1
for each row
begin
test_procedure(:new.value1);
end;
The procedure looks inside table1 and inserts in table2 hints about what should be added in table1 based on the current inserted/updated row.
Thanks in advance!!
I found it!
The problem was not the trigger, it was in the procedure. I was performing a "dirty read" based on the record ID that i was sending (the record id of a new row).
Even though my trigger is "after insert" it looks like my row can't be found by the procedure and i was basing all my operations on it.
Fixed it by adding more parameters to the procedure and passing :new values straight from the trigger for everything i needed.
A trigger transaction is depend on its statement transaction. Therefore you can not read uncommitted records. So you should transfer "test_procedure" codes into your trigger and use :New record values to insert data into table2.
Your code should look like this:
create or replace trigger test_trg
after insert or update on table1
for each row
begin
if inserting then
insert into table2(ID, F1, F2, ...)
values (NEW_ID_VALUE, :NEW.F1_VALUE, :NEW.F2_VALUE, ...);
elsif updating then
update table2
set F1 = :NEW.F1_VALUE
, F2 = :NEW.F2_VALUE
where TABLE1_ID_FK = :NEW.ID;
end if;
end;

How to Update Column of one table if Another table column value becomes zero In Oracle?

I have two tables of ITEM(Menu_Id,Menu_Status) & STOCK(Stock_Id,Menu_Id,Stock_Quantity).
Now I want to update the Menu_Status column of ITEM table, when the Stock_Quantity column of STOCK table value will be zero.
And also I implement this on Oracle Apex 5.0 .
I want to handle this in backend of database, when customer orders and Stock_Quantity will be minus(-) according to number of quantity is ordered.
Which one better for this? Trigger or Procedure? Please help me by providing code.
I tried this code but having ORA-24344: success with compilation error message!
create or replace trigger "KITCHEN_T11"
AFTER
insert or update on "KITCHEN"
for each row
when (NEW.quantity<= 0)
begin
declare
mid number;
begin
select m_id into mid from kitchen where k_id=:new.k_id;
update menu_item set status=0 where m_id=mid;
end;
end;
You should anyhow write a procedure to update item table. Only choice need to make is to call it from where.
If you know all the process who are updating stock table, and if this procedure can be placed there, it will be best option.
In case it is not possible, you can call this procedure from trigger.
CREATE OR REPLACE TRIGGER "STOCK_T1"
AFTER
insert or update on "STOCK"
for each row
WHEN (NEW.stock_quantity<= 0)
begin
update item set menu_status=0 where menu_id=:NEW.MENU_ID;
end;

oracle trigger select updated row

I'm trying to build a trigger which takes the specific updated row and insert it into another table, but I'm not able to build it.
This is what I was able to build:
CREATE OD REPLACE TRIGGER Z_ONUPDATELOGIN
AFTER UPDATE OF LAST_LOGGED_IN_DATE ON CMN_SEC_USERS csu
BEGIN
INSERT INTO Z_LOGIN (name, login_date)
select first_name||last_name,
last_logged_in_date
from cmn_sec_users usr
where usr.id=csu.id;
END;
When you deal with triggers you can use the :NEW and :OLD keyword to work with the new and old values of the row you are modifying. In your case try this:
CREATE OR REPLACE TRIGGER Z_ONUPDATELOGIN
AFTER UPDATE OF LAST_LOGGED_IN_DATE ON CMN_SEC_USERS
FOR EACH ROW
BEGIN
INSERT INTO Z_LOGIN (name, login_date)
VALUES (:NEW.first_name || :NEW.last_name,
:NEW.last_logged_in_date);
END;

Getting the value that fired the Oracle trigger

Am very new to Oracle triggers. Suppose I have a trigger on an insert in the table emp. Is there a way to find out what was the inserted record that fired the trigger. I wanted the trigger to have code that does something if the inserted record was a particular value.
Assuming you have a row-level trigger, you can simply use the :NEW pseudo-record
CREATE TRIGGER name_of_trigger
BEFORE INSERT ON emp
FOR EACH ROW
DECLARE
<<declare variables>>
BEGIN
IF( :new.ename = 'JUSTIN' )
THEN
<<do something if the newly inserted ENAME value is 'JUSTIN'>>
END IF;
END;
For a DDL trigger, the approach is completely different. In that case, the pseudofunctions ora_dict_obj_owner and ora_dict_obj_name will return the owner and name of the table that the DDL statement is operating on.
The row that is being insertes is available as NEW in the trigger
Check out the manual for more details.
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/create_trigger.htm#BABEBAAB
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS99955

ORACLE and TRIGGERS (inserted, updated, deleted)

I would like to use a trigger on a table which will be fired every time a row is inserted, updated, or deleted.
I wrote something like this:
CREATE or REPLACE TRIGGER test001
AFTER INSERT OR DELETE OR UPDATE ON tabletest001
REFERENCING OLD AS old_buffer NEW AS new_buffer
FOR EACH ROW WHEN (new_buffer.field1 = 'HBP00')
and it works.
Since I would like to do the same things if the row is inserted, updated, or deleted, I would like to know what's happening in the trigger.
I think I can manage to find if the row is inserted or updated (I can check the old_buffer with the new_buffer).
How can I know if the row has been deleted?
From Using Triggers:
Detecting the DML Operation That Fired
a Trigger
If more than one type of DML operation
can fire a trigger (for example, ON
INSERT OR DELETE OR UPDATE OF
Emp_tab), the trigger body can use the
conditional predicates INSERTING,
DELETING, and UPDATING to check which
type of statement fire the trigger.
So
IF DELETING THEN ... END IF;
should work for your case.
I've changed my code like this and it works:
CREATE or REPLACE TRIGGER test001
AFTER INSERT OR UPDATE OR DELETE ON tabletest001
REFERENCING OLD AS old_buffer NEW AS new_buffer
FOR EACH ROW WHEN (new_buffer.field1 = 'HBP00' OR old_buffer.field1 = 'HBP00')
DECLARE
Operation NUMBER;
CustomerCode CHAR(10 BYTE);
BEGIN
IF DELETING THEN
Operation := 3;
CustomerCode := :old_buffer.field1;
END IF;
IF INSERTING THEN
Operation := 1;
CustomerCode := :new_buffer.field1;
END IF;
IF UPDATING THEN
Operation := 2;
CustomerCode := :new_buffer.field1;
END IF;
// DO SOMETHING ...
EXCEPTION
WHEN OTHERS THEN ErrorCode := SQLCODE;
END;
The NEW values (or NEW_BUFFER as you have renamed them) are only available when INSERTING and UPDATING. For DELETING you would need to use OLD (OLD_BUFFER). So your trigger would become:
CREATE or REPLACE TRIGGER test001
AFTER INSERT OR DELETE OR UPDATE ON tabletest001
REFERENCING OLD AS old_buffer NEW AS new_buffer
FOR EACH ROW WHEN (new_buffer.field1 = 'HBP00' OR old_buffer.field1 = 'HBP00')
You may need to add logic inside the trigger to cater for code that updates field1 from 'HBP000' to something else.
Separate it into 2 triggers. One for the deletion and one for the insertion\ update.

Resources