Creating a trigger on Oracle 11g - oracle

I need to create a trigger that updates another table whenever the trigger table has an insert into command, or an after insert trigger.
I need to pull the id that's being inserted into the table in order to update the other table, how do I go about doing so?
In case that's confusing, another attempt at my question:
Table 1 has an after insert trigger. Said trigger updates table 2 based on one of the id values being inserted into table 1. How do I pull said id value from table 1 in the trigger?

You can use :new in your trigger to reference the values being inserted, for example
create or replace trigger <trigger_name>
after insert on <table_name>
for each row
declare
l_id number;
begin
select :new.id into l_id from dual;
-- now l_id contains the id of the inserted row, do what you want with it
end;
Don't take the example to literally; you don't have to first select :new.id into a variable, you can use it directly in SQL inside the trigger. I did it here just for illustration.
Take a look at the Oracle docs: Coding Triggers
However, you might also want to take a look at some arguments why you should think twice if you really need to put your logic into triggers: The Trouble with Triggers

CREATE OR REPLACE TRIGGER testempdel
AFTER insert ON testemp
FOR EACH ROW
BEGIN
update testdelvalues set salary=:New.sal;
END;
/
Trigger created.
Initially the salary is null
SQL> select * from testdelvalues;
EMPNO EMPNAME SALARY
---------- ---------- ----------
7369 SMITH
After inserting the value in the other table is updated
SQL> insert into testemp (empno,ename,sal) values (1231,'TESTUSER',1000);
1 row created.
SQL> select * from testdelvalues;
EMPNO EMPNAME SALARY
---------- ---------- ----------
7369 SMITH 1000

Related

Get the last updated row in an Oracle table

How can I get the last updated row in an Oracle table? I have a table named Employees and I will perform some updates on it. Then I want to find out which row was updated last (i.e. which employee was updated last).
The easiest way
A table with a field name updated type date
A trigger to update the column whenever any of the other columns are updated.
Then
SQL> create table test.t1_trigger ( c1 number, c2 number, updated date );
Table created.
SQL> create or replace trigger test.t1_trg_update
before update of c1,c2 on test.t1_trigger
referencing new as new old as old
for each row
begin
:new.updated := sysdate;
end;
/
Trigger created.
SQL> insert into test.t1_trigger values ( 1 , 1 , null );
1 row created.
SQL> commit ;
Commit complete.
SQL> update test.t1_trigger set c1=2 , c2=2 ;
SQL> commit ;
Commit complete.
SQL> select * from test.t1_trigger ;
C1 C2 UPDATED
---------- ---------- -------------------
2 2 05.11.2021 12:18:30

Oracle - update same table on which trigger is fired

I have a table temp_table with the following columns
Id number,
name varchar,
Password varchar,
pwd_change_date timestamp
I want to capture the timestamp in pwd_change_date column only when password column is changed.
So basically i want to use update statement inside the trigger to update timestamp value in pwd_change_date column for the same record.
Example
When a password is changed for one user, I want to capture the timestamp value in pwd_change_date for the same record.
I tried with before insert and after insert of password on temp_table, but getting mutation error. Is it allowed in Oracle to update the Same row/table on which trigger is fired?
You don't need to update the table again; you can modify the data before it is inserted, with a before-insert row level trigger, e.g.:
create trigger trig_pwd_date
before insert or update on temp_table
for each row
when (old.password is null and new.password is not null or new.password != old.password)
begin
:new.pwd_change_date := systimestamp;
end;
/
db<>fiddle demo
This used the new and old correlation names to decide if the password value has changed; and the new correlation name to assign the system time to the field in the pseudorecord, which becomes the column value when the insert completes.
Hopefully you aren't storing plain-text passwords in your table.
SQL> create table temp_table (password varchar2(50), pwd_change_date TIMESTAMP);
Table created.
SQL> create trigger trig_pwd_date
before insert or update on temp_table
for each row
when (old.password is null and new.password is not null or new.password != old.password)
begin
:new.pwd_change_date := systimestamp;
end; 2 3 4 5 6 7
8 /
Trigger created.
SQL> set time on
15:28:42 SQL> insert into temp_table values ('23456',sysdate);
1 row created.
15:29:01 SQL> commit;
Commit complete.
15:29:09 SQL> select * from temp_table;
PASSWORD
PWD_CHANGE_DATE
12345
21-SEP-20 03.28.02.370377 PM
23456
21-SEP-20 03.29.01.478017 PM

Oracle trigger to update a column value in the same table

I am in the need of a trigger which will fire on any insert or updates on the specific table and while inserting or updating will substitute a credit card number column of the new row to something bogus such as "1111 1111 1111 1111"
Here is what I cooked up but it doesn't seem to work.
CREATE or REPLACE TRIGGER trigger_name AFTER INSERT ON table1
FOR EACH ROW
BEGIN
update table1 set cc_number_field = '11';
END;
I am on Oracle 10 if that matters.
It's much easier to manipulate the incoming :NEW line with a "before" trigger:
CREATE OR REPLACE TRIGGER table1_cc_trigger
BEFORE INSERT OR UPDATE ON table1
FOR EACH ROW
BEGIN
:NEW.cc_number_field := '1111 1111 1111 1111';
END;
/
Not tested:
CREATE OR REPLACE TRIGGER t
BEFORE
INSERT on ON table1 FOR EACH ROW
begin
:new.cc_number_field = '11';
END;
PL/SQL Reference - Triggers

Concatenate String with a column in trigger

I have a table called TBL_CAS. In that, FLD_ID as auto increment column and another column is called FLD_CAS_CODE. Now I need to add CAS- as a prefix to FLD_ID and Insert into FLD_CAS_CODE. I need to do this in trigger. I was tried with the below code, But the data in not inserting, What is the problem ?
CREATE OR REPLACE TRIGGER TBL_CAS_TRG
BEFORE INSERT ON TBL_CAS
FOR EACH ROW
BEGIN
:NEW.FLD_CAS_CODE := TO_CHAR ('CAS')||'-'||:NEW.FLD_ID;
END;
I mean `"cas-"+"fld_id"="cas-fld_id"'
You don't need to put TO_CHAR() around things which are already charcater datatypes. But you should cast the numeric identifier (rather than relying on implicit conversion):
:NEW.FLD_CAS_CODE := 'CAS-'||TRIM(TO_CHAR (:NEW.FLD_ID));
which part isn't working exactly? as your trigger seem to work just fine.
SQL> create table TBL_CAS( FLD_ID number, FLD_CAS_CODE varchar2(20));
Table created.
SQL> CREATE OR REPLACE TRIGGER TBL_CAS_TRG
2 BEFORE INSERT ON TBL_CAS
3 FOR EACH ROW
4 BEGIN
5 :NEW.FLD_CAS_CODE := TO_CHAR ('CAS')||'-'||:NEW.FLD_ID;
6 END;
7 /
Trigger created.
SQL> insert into TBL_CAS (fld_id) values (1001);
1 row created.
SQL> select * From TBL_CAS;
FLD_ID FLD_CAS_CODE
---------- --------------------
1001 CAS-1001
SQL>
This will also work fine:
CREATE OR REPLACE TRIGGER TBL_AREA_CODES_TRG
BEFORE INSERT ON TBL_AREA_CODES
FOR EACH ROW
BEGIN
:NEW.OBRM_AREA_CODE := :NEW.STATE_CODE ||'-'||:NEW.DIST_CODE ||'-'||:NEW.CITY_CODE ||'-'||:NEW.AREA_CODE ;
END;

Oracle 'statement level' Trigger

I want to create a Statement level Trigger which means I want to insert only one record into table EMP_AUDIT when 1 or more rows are inserted into table EMP. For example: if I have 10 records inserted into EMP, then only 1 record should be inserted into EMP_AUDIT table.
There are no constraints on columns. (i.e. can be NULL)
I tried to use the following trigger but it gives me the Error(2,2): PL/SQL: SQL Statement ignored
Error(2,14): PL/SQL: ORA-00947: not enough values
CREATE OR REPLACE
TRIGGER TRIG_EMP AFTER INSERT ON EMP
BEGIN
INSERT INTO EMP_AUDIT
VALUES (TRANID,EMPNUM,SYSDATE);
END;
CREATE TABLE EMP
(TRANID NUMBER,
EMPNUM VARCHAR2(100),
EMPLOC VARCHAR2(100));
CREATE TABLE EMP_AUDIT
(EVENTID NUMBER,
EMPNUM VARCHAR2(100),
ENTRDATE DATE);
The statement-level trigger (which you have) cannot see the data that was inserted. After all, if there were 10 rows inserted, what values should the columns be for your audit table?
You need a row-level trigger for this to work, e.g.:
CREATE OR REPLACE
TRIGGER TRIG_EMP
AFTER INSERT ON EMP
FOR EACH ROW
BEGIN
INSERT INTO EMP_AUDIT
VALUES (:NEW.TRANID,:NEW.EMPNUM,:NEW.SYSDATE);
END;
Use this piece of code:
CREATE OR REPLACE TRIGGER
TRIG_EMP
AFTER INSERT ON EMP
FOR EACH ROW
BEGIN
INSERT INTO EMP_AUDIT
VALUES (:NEW.TRANID,:NEW.EMPNUM,:NEW.SYSDATE);
END;

Resources