how to update a column using oracle trigger - oracle

CREATE OR REPLACE TRIGGER demands
AFTER INSERT ON demand
FOR EACH ROW
DECLARE
MRPs number;
BEGIN
SET demand.MRP=10;
dbms_output.put_line('Salary difference: ' || :NEW. PRODUCT_NAME);
END;
I want to set the mrp =value x (which is not same every time for solving the issue we are supposing it to be 10 ) after the row is inserted

Use :NEW.MRP := 10 in a BEFORE INSERT trigger (if you use AFTER INSERT then the value will already have been inserted and you cannot change it).
CREATE OR REPLACE TRIGGER demands
BEFORE INSERT ON demand
FOR EACH ROW
BEGIN
:NEW.MRP := 10;
END;
/
db<>fiddle here

Related

Update of column value within a trigger

Before insert or update of any columns I want to update 1 system column with standard hash MD5 of all table columns, trigger is attached to. My intention is not to tailor this trigger with enumeration of all columns for each trigger and have a function that returns concatenated list of columns per table.
Table DDL:
create table TEST (
id int,
test varchar(100),
"_HASH" varchar(32)
);
Here is my trigger DDL that I would love to work :
CREATE TRIGGER TEST_SYS_HASH_BEFORE_INSERT_OR_UPDATE
BEFORE INSERT OR UPDATE
ON TEST
FOR EACH ROW
DECLARE
var_columns VARCHAR2(10000);
BEGIN
var_columns := FUNC_LISTAGG_EXT(‘TEST');
EXECUTE IMMEDIATE 'SELECT STANDARD_HASH(' || var_columns || ', ''MD5'') from dual'
INTO :new."_HASH";
END;
However this is simply taking headers and set same hash for every row. If I should do this manually , trigger would look like this, what works as I desire, but create it for several tens of tables would be overwhelming
CREATE OR REPLACE TRIGGER TEST_SYS_HASH_BEFORE_INSERT_OR_UPDATE
BEFORE INSERT OR UPDATE
ON TEST
FOR EACH ROW
DECLARE
var_columns VARCHAR(10000);
BEGIN
var_columns := FUNC_LISTAGG_EXT('TEST');
SELECT STANDARD_HASH( :new."ID" || :new."TEST" , 'MD5' )
INTO :new."_HASH";
FROM DUAL;
END;
So my question is whether solution is achievable
Note:
FUNC_LISTAGG_EXT function returns concatenated list of columns from system view

how to pass a whole row as record to a function in oracle triggers

I create a oracle package with function where in the input is a whole row and the output is varray. i want to use this package function to apply on all the rows of a table using trigger as soon as new record is inserted. I tried like this but the output is bad bind variable
create or replace trigger custdata_caferrors
before insert or update on customer_data
referencing new as n old as o
for each row
declare
v_remarks varchar(500) :=' ';
t_remarks caf_errors :=caf_errors();
rec customer_data%rowtype;
begin
-- rec = :n;
t_remarks := CUSTDATA_VERIFY.VERIFY_TERMSTATUS(:n);
for x in 1..t_remarks.count
loop
v_remarks :=v_remarks||' , '||t_remarks(x);
end loop;
:n.record_status1 :=v_remarks;
end;
/
Unfortunately there is no way to reference a whole new row in a trigger. I agree it would be neat if this were possible, but alas.
So you will have to explicitly populate your rec variable with the column values you require and pass that to your function, like this
create or replace trigger custdata_caferrors
before insert or update on customer_data
referencing new as n old as o
for each row
declare
v_remarks varchar(500) :=' ';
t_remarks caf_errors :=caf_errors();
rec customer_data%rowtype;
begin
rec.id := :n.id;
rec.col1 := :n.col1;
-- etc
t_remarks := CUSTDATA_VERIFY.VERIFY_TERMSTATUS(rec);
for x in 1..t_remarks.count
loop
v_remarks :=v_remarks||' , '||t_remarks(x);
end loop;
:n.record_status1 :=v_remarks;
end;
/
Do you really need to pass the whole row to CUSTDATA_VERIFY.VERIFY_TERMSTATUS()? If not you might get away with populating just the columns the function actually uses (although that does contravene the Law of Demeter).

trigger save old record in another column in the same table oracle

I have a table called customer_history
where it includes customer_id, Visit_Date, Action_Done
i added 2 new columns old_visit_date, old_action_date and created the following trigger where when updating visit_date the old date column to be add into old_action_date column as follows:
CREATE OR REPLACE TRIGGER customer_history
BEFORE UPDATE
OF visit_date
ON TESTING FOR EACH ROW
Declare visit_date date;
BEGIN
:NEW.old_visit_date := visit_date ;
END;
/
however when updating the table the old_visit_date is not updated ????!!!!
Use:
BEGIN
IF UPDATING ('VISIT_DATE') THEN
:NEW.old_visit_date := OLD.visit_date ;
END IF;
END;
/

TRIGGERS insert same table - PLSQL

Here's my problem:
I have to transform something like this
Into this in the same table
I've tried triggers but I have mutating issues, I have no control about the inserts but I need to do that for every row with value larger than 1.
Any sugestions?
Depending on the number of transactions you're looking at, it may not be a feasible approach, but you might try something along these lines:
CREATE OR REPLACE TRIGGER {TRIGGER NAME}
BEFORE INSERT ON {TABLE HERE}
FOR EACH ROW
DECLARE
l_val INTEGER;
BEGIN
l_val := :new.value - 1;
IF l_val > 0 THEN
:new.value := 1;
FOR i IN 1..l_val LOOP
INSERT INTO {TABLE HERE}
VALUES (:new.name, 1);
END LOOP;
END IF;
END {TRIGGER NAME};
/
You need to use view and instead of trigger.
Creating table create table testing_trig (c char(1), i integer);
Creating view create or replace view testing_trig_view as select * from testing_trig;
Creating trigger
CREATE OR REPLACE TRIGGER testing_trg
INSTEAD OF INSERT
ON testing_trig_view
BEGIN
FOR i IN 1 .. :NEW.i
LOOP
INSERT INTO testing_trig VALUES (:NEW.c, 1);
END LOOP;
END;
/
Insert into view insert into testing_trig_view values ('A', 3);
Validate
SQL> select * from testing_trig;
C I
- ----------
A 1
A 1
A 1

How to get number of rows affected by a statement when inside that statement's trigger

I have a statement level trigger that fires whenever INSERT UPDATE or DELETE operations are performed on a table (called customers). I want to display a message (to DBMS_OUTPUT) containing the number of rows that were inserted/updated/deleted.
I just want one message for each triggering statement, eg
'4 rows were inserted into customers table'.
How can I access the number of rows that are affected by the triggering statement from INSIDE the trigger declaration, ie XXX in the code below:
CREATE OR REPLACE TRIGGER customer_changes_trigger_2
AFTER INSERT OR UPDATE OR DELETE ON customers
DECLARE
v_operation VARCHAR(10);
v_number_rows NUMBER;
BEGIN
v_number := XXX;
IF INSERTING THEN
v_operation := 'inserted';
END IF;
IF UPDATING THEN
v_operation := 'updated';
END IF;
IF DELETING THEN
v_operation := 'deleted';
END IF;
DBMS_OUTPUT.PUT_LINE
(v_number_rows|| ' rows were ' || v_operation || ' from customers.');
END;
Can't find anything in the documentation, any help appreciated!
One way is to use a global variable to track the number of rows as there is no other way to get the row count from a statement level trigger. You would then need three triggers... one statement level to initialise the variable before the statement is run, one row level to add one to the variable for each row, one statement level to use the row count however you wish. First, set up the variable and a few procedures to help it:
create or replace package PKG_ROWCOUNT is
NUMROWS number;
procedure INIT_ROWCOUNT;
procedure ADD_ONE;
function GET_ROWCOUNT
return number;
end PKG_ROWCOUNT;
/
create or replace package body PKG_ROWCOUNT as
procedure INIT_ROWCOUNT is
begin
NUMROWS := 0;
end;
procedure ADD_ONE is
begin
NUMROWS := Nvl(NUMROWS, 0) + 1;
end;
function GET_ROWCOUNT
return number is
begin
return NUMROWS;
end;
end PKG_ROWCOUNT;
/
The first trigger to initialise the variable:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_1
before insert or update or delete
on CUSTOMERS
begin
PKG_ROWCOUNT.INIT_ROWCOUNT;
end;
The second to update per row:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_2
after insert or update or delete
on CUSTOMERS
for each row
begin
PKG_ROWCOUNT.ADD_ONE;
end;
/
The third to display the total:
create or replace trigger CUSTOMER_CHANGES_TRIGGER_3
after insert or update or delete
on CUSTOMERS
begin
Dbms_output.
PUT_LINE(PKG_ROWCOUNT.GET_ROWCOUNT || ' rows were affected.');
end;
I'm not 100$ sure if it's available inside AFTER trigger body, but you can try examining sql%rowcount

Resources