trigger save old record in another column in the same table oracle - 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;
/

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 update a column using oracle trigger

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

How I can create a trigger with a derived attribute?

I have a database of a video store, to ask the question that I have exposed, I thought about updating an age attribute that corresponds to the actors, but this doesn't make sense (as I show below in an example)
CREATE TABLE dobs ( dob date, age number(3));
insert into dobs values ((to_date('1999-10-04','yyyy-mm-dd')),NULL);
CREATE OR REPLACE FUNCTION get_age
(
fnacimiento date
)
return int
is edad int;
begin
select floor(months_between(sysdate,dob)/12) into edad
from dobs
where dob=fnacimiento;
return edad;
end get_age;
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dobs
FOR EACH ROW
BEGIN
:new.age := get_age(:new.dob);
END;
You don't need a function in order to update that column. Even no need to use a SELECT Statement. Just rearrange the trigger as :
CREATE OR REPLACE TRIGGER agec BEFORE INSERT OR UPDATE ON dobs
FOR EACH ROW
BEGIN
:new.age := floor(months_between(sysdate,:new.dob)/12);
END;
Trigger will be fired once at time of insert or update of record in the table so you will get the age of actor when insert/update is executed, not as of today.
So better solution is to create a view instead of trigger as follows:
Create or replace view dobs_vw
As
Select t.* floor(months_between(sysdate,t.dob)/12) as age_asof_today
From your_table t

Create Trigger to display message “Restock- <item-name>”, when a item quantity reaches 10 and below while updating or inserting item

table
Stock:
ITEMID NUMBER PRIMARY KEY
DESCRIPTION VARCHAR2(30)
QUANTITY NUMBER
CREATE OR REPLACE TRIGGER trig_1 BEFORE
UPDATE OR INSERT ON stock
FOR EACH ROW
DECLARE
v_des VARCHAR2(30);
v_quan NUMBER;
BEGIN
SELECT
quantity,
description
INTO
v_quan,
v_des
FROM
stock;
IF v_quan <= 10 THEN
dbms_output.put_line('Restock' || v_des);
END IF;
END;
You need to use :NEW cursor to refer to the new value that is being inserted or updated as following:
CREATE OR REPLACE TRIGGER TRIG_1 BEFORE
UPDATE OR INSERT ON STOCK
FOR EACH ROW
BEGIN
IF :NEW.QUANTITY <= 10 THEN
DBMS_OUTPUT.PUT_LINE('Restock - ' || :NEW.DESCRIPTION);
END IF;
END;
/
Make sure that you SET SERVEROUTPUT ON while inserting/updating the table data so that it is displayed in the output.
Cheers!!

How to set new date entries to current date?

I am trying to create a trigger. It is supposed to update any new date entry to sysdate. So far, I have the following code. However, I get "invalid table name" and "SQL statement ignored" errors.
CREATE OR REPLACE TRIGGER new_orders
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE
SET order_date := SYSDATE;
END IF;
END;
/
CREATE OR REPLACE TRIGGER new_orders
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
:NEW.order_date := SYSDATE;
END;
/

Resources