Oracle trigger to update table with current row state - sql

I have a table in Oracle with Timestamp field, a key field and 2 other columns. Am looking to create a trigger which would update another table with just the current state row data based on key, timestamp. Am new to trigger, any inputs and / or recommendation would be highly appreciated.

create or replace TRIGGER A
AFTER INSERT
ON A1
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
BEGIN
UPDATE C SET COLC=:new.colc, D=:new.cold, TIMESTAMP=:new.timestamp WHERE KEY=:new.key;
EXCEPTION
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END A;

Related

This Oracle trigger has problems

create or replace NONEDITIONABLE TRIGGER SumUpdate AFTER INSERT ON stavkaotpremnice FOR EACH ROW
declare pragma autonomous_transaction;
begin
UPDATE otpremnica a
set a.ukupno=
(SELECT SUM(ukupno)
FROM stavkaotpremnice
WHERE brojotpremnice =: new.brojotpremnice)
WHERE a.brojotpremnice = :new.brojotpremnice;
commit;
end;
This trigger is to sum values of a column called "ukupno" in table stavakaotpremnice then store it in another table otpremnica in a column also called "ukupno".
The trigger check if the id(brojotpremnice) is the same and make the sum.
Brojotpremnice is a foreign key from table otpremnica.
Does anyone know why it is totally ignoring the first entry?
If i put rows in stavkaotpremnica i just count the first entry.
This type of problem can be solved via incremental addition as follows:
UPDATE otpremnica a
set a.ukupno = a.ukupno + :new.ukupno
WHERE a.brojotpremnice = :new.brojotpremnice;
Also, please read about pragma autonomous_transaction. Why it is used? Intentional? If you have no idea, read it. (It separates the transaction)

UPSERT inserts duplicate null entry into table (ORACLE)

I am trying to make an upsert trigger on ORACLE via PL/SQL by checking some examples, i am doing fine, i think it is the last step i should only configure. My requirement is that :
A system that will insert to that field will remain one column always null, so i will read column value from another table, then upsert it with inclusion of that value.
d2c_region_locale_config holds d2c_is_active value, so i firstly read that value regarding to locale condition then trigger inserts or updates to table with addition of this value on active_for_d2c column.(for update i am using locale and country columns as it is shown on where clause, they are not PK but has not null condition)
So i've created this trigger:
CREATE OR REPLACE TRIGGER BL_PIM_LOCALE_COUNTRY
BEFORE INSERT OR UPDATE ON PIM_LOCALE_COUNTRY REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
l_active_for_d2c INTEGER;
BEGIN
if :NEW.active_for_d2c is null then
DELETE from pim_locale_country where active_for_d2c is null;
select distinct(d2c_isactive) into l_active_for_d2c from d2c_region_locale_config where d2c_locale= :NEW.locale;
UPDATE pim_locale_country
SET locale = :NEW.locale, locale_name = :NEW.locale_name,
country = :NEW.country, country_name = :NEW.country_name, isdummy = :NEW.isdummy,
active_for_d2c = l_active_for_d2c, itextpos = :NEW.itextpos, locale_charset = :NEW.locale_charset,
fallback_locale = :NEW.fallback_locale, default_for_lang = :NEW.default_for_lang, opeclang = :NEW.opeclang
where locale = :NEW.locale and country = :NEW.country;
IF ( sql%notfound ) THEN
INSERT INTO PIM_LOCALE_COUNTRY (locale,locale_name,country,country_name,isdummy,active_for_d2c,itextpos,locale_charset,fallback_locale,default_for_lang,opeclang)
VALUES (:NEW.locale, :NEW.locale_name,:NEW.country,:NEW.country_name,:NEW.isdummy,l_active_for_d2c,:NEW.itextpos,:NEW.locale_charset,:NEW.fallback_locale,:NEW.default_for_lang,:NEW.opeclang);
END IF;
end if;
END;
It currently does the job, reads value and inserts or updates the existing locale-country couple for other values. But critical thing is that, table always has one "null" value(Please check screenshot), even that i run delete statement at the beginning on my trigger. So my question would be how to delete, or how to make this approach on trigger side ?
Many thanks for answers!
Trigger before insert doesn't block insert itself, so you insert that record twice. That is, once your trigger done its work (inserted or updated record), oracle will proceed with insert (or update) using values that stand in NEW record of your trigger. If trigger modifies NEW., it will be stored as you changed it, but if trigger inserts something itself, you can get more records.
You can use instead of insert or update triggers, and then oracle will not run its own inserts/updates after trigger finishes.
But more common way for 1-record triggers is to modify fields in NEW, for this case field NEW.d2c_is_active.
It looks like this (possible typos, please check)
CREATE OR REPLACE TRIGGER BL_PIM_LOCALE_COUNTRY
BEFORE INSERT OR UPDATE ON PIM_LOCALE_COUNTRY REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
if :NEW.active_for_d2c is null then
select d2c_isactive
into :NEW.active_for_d2c
from d2c_region_locale_config
where d2c_locale= :NEW.locale and rownum<=1;
end if;
END;

How to update the same table in SAP HANA Triggers

I am trying to write a trigger in SAP HANA to update a field of a table when new records are being inserted to that table. Following is a sample trigger that I have written.
CREATE TRIGGER SAMPLE
AFTER INSERT ON TARGET_TABLE
REFERENCING NEW ROW NEW_ROW
FOR EACH ROW
BEGIN
UPDATE TARGET_TABLE SET VALID_FROM='2018-02-01' WHERE ITEM=:NEW_ROW.ITEM
END
When I try this, I get the error:
Modification of subject table in trigger not allowed
Is there a way by which I can achieve this?
This suggests to use the transition variable NEW_ROW, appreciate if a code sample can be provided.
You don't actually need to create trigger for your requirement as I can see from your post (of course if it is only updating a date field)
You can define the VALID_FROM column with a DEFAULT value
For example,
Create Column Table DefaultColumnTable (
Id int,
Code varchar(5),
VALID_FROM date default '2018-02-01'
)
So whenever a new row is inserted, unless an alternative value is stated the valid_from column will be populated with default date specified in the DDL command above.
The users can change the valid_from field value without any problem
#Kalpa, maybe you can use BEFORE INSERT Trigger
Please check following sample
create trigger TriggerTable_B_INS BEFORE INSERT on TriggerTable
REFERENCING NEW ROW mynewrow
FOR EACH ROW
begin
declare lv_d date;
lv_d := '20180201';
mynewrow.VALID_FROM = :lv_d;
end;
You set only the new row columns before Insert command executes over the target table.
You don't explicitly execute an INSERT command, just set new values for new row columns. That's all
I hope it helps

HANA: SQL Trigger to set a row's last modified date?

So, I understand how to create a trigger in HANA, but the examples in the HANA reference material do not mention how a trigger on Table A can update Table A; instead the material is always trigger on A updates B like the following example from the SAP docs:
CREATE TRIGGER TEST_TRIGGER_VAR_UPDATE
AFTER UPDATE ON TARGET
REFERENCING NEW ROW mynewrow, OLD ROW myoldrow
FOR EACH ROW
BEGIN
INSERT INTO SAMPLE_new VALUES(:mynewrow.a, :mynewrow.b);
INSERT INTO SAMPLE_old VALUES(:myoldrow.a, :myoldrow.b);
INSERT INTO SAMPLE VALUES(0, 'trigger');
END;
What's the preferred way of updating a column such as a LastModifiedDate? Would I set :mynewrow.LastModifiedDate = NOW(), or should I perform an UPDATE where the ID matches the ID of mynewrow?
As of SPS8, a HANA SQL Trigger can only perform INSERT, UPDATE, and DELETE statements against other tables. If you try to create a self-referencing Trigger, you'll find the following error message:
Modification of subject table in trigger not allowed

Create a trigger that updates a column on one table when a column in another table is updated

i have two tables
Order(id, date, note)
and
Delivery(Id, Note, Date)
I want to create a trigger that updates the date in Delivery when the date is updated in Order.
I was thinking to do something like
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE
ON Order
DECLARE
BEGIN
UPDATE Delivery set date = ??? where id = ???
END;
How do I get the date and row id?
thanks
How do i get the date and row id?
Assuming these are columns on your ORDER table called DELIVERY_DATE and ID your trigger should look something like this:
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE ON Order
FOR EACH ROW
BEGIN
if :new.delivery_date != :old.delivery_date
then
UPDATE Delivery d
set d.delivery_date = :new.delivery_date
where d.order_id = :new.id;
end if;
END;
Note the FOR EACH ROW clause: that is necessary to reference values from individual rows. I have used an IF construct to test whether to execute the UPDATE on Delivery. If you have no other logic in your trigger you could write it like this...
CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE OF delivery_date ON Order
FOR EACH ROW
BEGIN
UPDATE Delivery d
set d.delivery_date = :new.delivery_date
where d.order_id = :new.id;
END;
I have answered the question you asked but, as an aside, I will point out that your data model is sub-optimal. A properly normalized design would hold DELIVERY_DATE on only one table: DELIVERY seems teh logical place for it.
Use the OLD and NEW bind variables. OLD references the row or column being updated before the change is made; NEW references it after the change.
CREATE OR REPLACE TRIGGER trig1
BEFORE UPDATE
ON order REFERENCING NEW AS new
FOR EACH ROW
BEGIN
UPDATE delivery
SET ddate = :new.ddate
WHERE id = :new.id;
END;
You can modify the REFERENCING clause to give your bind variables different names. You can include OLD as <name> too. Example:
CREATE OR REPLACE TRIGGER trig1
BEFORE UPDATE
ON order REFERENCING OLD AS old_values NEW AS new_values
...
If you don't want to change the default names of "old" and "new", you can leave out the REFERENCING clause completely.
There is an implicit new and old reference in the trigger in the form of:
REFERENCING OLD AS OLD NEW AS NEW
You can write to the :NEW value but not to the :OLD value.
UPDATE Delivery set date = :new.delivery_date where id = :new.id;
CREATE OR REPLACE TRIGGER "BUR_TABLENAME" BEFORE
UPDATE ON "TABLE" FOR EACH ROW
BEGIN
If :new.active_date is not null Then
:new.active_date := TRUNC(:new.active_date);
End If;
END;
Template:
CREATE OR REPLACE TRIGGER TRIGGER_NAME
BEFORE
UPDATE
ON TABLE_NAME
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
V_VARIABLE NUMBER (1);
BEGIN
//Do Stuff;
null;
end;
Whenever there is a need for this kind of trigger, have a good look at your design. Is there really a need for a separate delivery record? Does an order really have more than 1 delivery ?
Triggers seem nice but they do tend to mess things up pretty quickly.