I work with Oracle and I'm looking for something like "ON UPDATE" in MySQL.
How can I set a timestamp automatically in my modified column every time a row in a table was changed/ updated?
With a trigger.
create or replace trigger trg_biu_test
before insert or update on test
for each row
begin
:new.timestamp_column := sysdate;
end;
/
Related
Trigger under question is for Table which has ETL in ODI but user also has option to edit certain **columns **
if they want to adjust them. This is done using APEX
Trigger is used to change two columns : Changed_by and Change_on.
Both indicating Changes done on APEX PAGE only.
The issue comes when ODI load is run and is MERGE INSERT UPDATE , Trigger thinks its updating and changes the above two columns to "NULL" as its a manual update done by ODI and not on APEX.
Solution
For each Editable Column, there should be a logic which checks NEW: <> :OLD, but as i have 15 columns need to write a lot of code.
Are there others way to achieve this ?
create or replace TRIGGER DW.TRG BEFORE
UPDATE ON DW.TABLE
REFERENCING
NEW AS new
OLD AS old
FOR EACH ROW
BEGIN
IF updating THEN
SELECT
SYSDATE,
v('APP_USER')
INTO
:new.changed_on_dt,
:new.changed_by
FROM
dual;
END IF;
END;
Check if an apex session exists for the current database session and only execute when it is the case.
create or replace TRIGGER DW.TRG BEFORE
UPDATE ON DW.TABLE
REFERENCING
NEW AS new
OLD AS old
FOR EACH ROW
BEGIN
IF SYS_CONTEXT('APEX$SESSION','APP_SESSION') IS NOT NULL AND updating THEN
:new.changed_on_dt := SYSDATE;
:new.changed_by := SYS_CONTEXT('APEX$SESSION','APP_USER');
END IF;
END;
Notes
avoid the SELECT FROM DUAL, you can just assign the values in the trigger.
The "V" functions are pretty slow. For a while there have been sys_context settings that store the session and user data. Those are a lot faster than a function call to the "V" function.
You could make it so that it never overwrites a non-null value with a null one:
IF v('APP_USER') IS NOT NULL
THEN
:new.changed_by := v('APP_USER');
:new.changed_on_dt := SYSDATE;
END IF;
I have requirement wherein I need to get the affected row if a row gets updated or added. I have seen many examples wherein we can use :new or :old keywords to get the columns e.g. new.columnName but is there a way to get the complete row. Code snippet is as below. Thanks in advance.
CREATE OR REPLACE TRIGGER TRG_134673016571507516045
AFTER
INSERT OR UPDATE ON employees
FOR EACH ROW
DECLARE
content varchar2(4000) := '||:NEW.row||';
BEGIN
///////
END;
I have a table named info_1,with 3 columns those are id,name,and operation.
Now when we insert or update a row, a trigger fires to fill the operation column with the kind of triggering event we are performing, i.e either insert or update.. I am unable to create such a trigger where user only gives information about id,name and operation column fills by itself through trigger. need help.
You can set the operation using a case statement like this:
create or replace trigger info_1_tr
before insert or update on info_1
for each row
begin
:new.operation := case when updating then 'UPDATE' else 'INSERT' end;
end;
/
This might appear a simple query for most of you, but I am a beginner in Oracle DB.
A table has been created with below script-
CREATE TABLE PLAN_TABLE
(
PL_ID DECIMAL(10,0) PRIMARY KEY NOT NULL
,PL_NAME VARCHAR2(300) DEFAULT NULL
,UPDATED_TS TIMESTAMP DEFAULT SYSDATE NOT NULL
,DELETE_FLAG DECIMAL(10,0) DEFAULT 0 NOT NULL
);
The requirement is to have SYSDATE for UPDATED_TS for any new record inserted into the table and also in case when the DELETE_FLAG is updated to 1. Can it be done by trigger?
The below trigger was created-
CREATE OR REPLACE TRIGGER PT_BEFORE_INSERT_TR
BEFORE INSERT ON PLAN_TABLE
FOR EACH ROW
BEGIN
SELECT SYSDATE INTO :new.UPDATED_TS FROM DUAL;
dbms_output.put_line('Inserted');
END;
/
Below error was encountered while inserting record into the table-
error: ORA-04091: table I60_SCH04.PLAN_TABLE is mutating, trigger/function may not see it
Can you please help in letting me know that where am I committing the mistake? Is there any better way to achieve the requirement based upon INSERT/UPDATE?
The actual error you get is due to the fact that you try to select from a table that you actually are changing. To prevent the issue there are a couple of methods, but in you case things are really simple.
SYSDATE is a function, that you could call directly inside PL/SQL block (which a trigger actually is) and use the value returned to update the set the column value
CREATE OR REPLACE TRIGGER PT_BEFORE_INSERT_TR
BEFORE INSERT ON PLAN_TABLE
FOR EACH ROW
BEGIN
:new.UPDATED_TS := sysdate;
dbms_output.put_line('Inserted');
END;
/
OK, this covers the insert part.
For updating - once again, many options. One could be - change your trigger to BEFORE INSERT OR UPDATE ON PLAN_TABLE.
In this case whenever you issue update or insert - this trigger is fired for each row and updates the date column accordingly.
And of course you could use particular checks available in triggers, something like
IF INSERTING OR UPDATING('DELETE_FLAG') THEN
...
END IF;
and code in the logic you need.
I'm migrating my Oracle database to MariaDB, and I am unsure how to create a self-referencing ID on one of my tables.
Essentially, if a belongs_to_id is not specified, it will assume that it belongs to itself (and be the same as the ID generated ON INSERT); however, if a belongs_to_id has been specified, then it will use that instead.
The reason I do this is because I have posts and replies stored in the same table. If the id = belongs_to_id then it's an initiating post, whereas if it differs, it is a reply to another post.
I've thought about letting my application (Node JS) do a quick UPDATE using last_insert_id - but it seems rather messy and I'd like to avoid that if possible.
Here's what I use in Oracle - does anyone know how I replicate this in MariaDB please?
CREATE OR REPLACE TRIGGER my_trigger
BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
:new.id := my_sequence.NEXTVAL;
:new.belongs_to_id := NVL(:new.belongs_to_id,:new.id);
END;
/
This should work in MariaDb as it closely conforms to SQL-99 syntax.
CREATE OR REPLACE TRIGGER my_trigger
BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
:new.id := my_sequence.NEXTVAL;
:new.belongs_to_id := NVL(:new.belongs_to_id,:new.id);
END;
IF you set your new ID to be an auto increment then you can only use an after insert trigger. Something like
CREATE OR REPLACE TRIGGER my_trigger
AFTER INSERT ON my_table
FOR EACH ROW
v_id NUMBER:
BEGIN
v_id := LAST_INSERT_ID();
:old.belongs_to_id := NVL(:old.belongs_to_id,v_id);
END;
Maybe simply
When INSERTing, set belongs_to_id to NULL (no TRIGGER).
When SELECTing, do COALESCE(belongs_to_id, id).
Meanwhile, completely switch from SEQUENCE to AUTO_INCREMENT (again no TRIGGER).