Update column in another table with trigger - sql

I would like to update a column in another table with the code below but I get a error that the trigger is invalid.
Whats wrong with it?
CREATE OR REPLACE TRIGGER UPDATE_PAYMENT
AFTER INSERT OR UPDATE ON PAYMENT
for each row
begin
update PAYMENTTYPE PT
set PT.PAYMENTTYPECOLUMN = PAYMENT.PAYMENTTYPECOLUMN
where PT.ID = :NEW.ID and PT.ID2 = :NEW.ID2;
end UPDATE_PAYMENT;

In your trigger you refer twice to PAYMENT columns by :NEW., and this is correct, while the third time you use PAYMENT., which is wrong.
The trigger should be:
CREATE OR REPLACE TRIGGER UPDATE_PAYMENT
AFTER INSERT OR UPDATE ON PAYMENT
for each row
begin
update PAYMENTTYPE PT
set PT.PAYMENTTYPECOLUMN = :NEW.PAYMENTTYPECOLUMN -- <------ HERE
where PT.ID = :NEW.ID and PT.ID2 = :NEW.ID2;
end UPDATE_PAYMENT;

Related

Oracle SQL Trigger with Conditional Update based on Information in Separate Table

I have two tables:
cost_bank (this is where I want the trigger)
master_data (this table has information I need to check)
I want to build an "after insert" trigger on cost_bank which runs when the newly inserted cost_bank.work_code is in the master_data table with a master_data.charge_type = 'EX'. If that scenario is true, I want the trigger to update the newly added row only (can specify by ID) in cost_bank with the value from master_data.r_cost_center for cost_bank.cost_center.
Here is what I have so far:
CREATE OR REPLACE TRIGGER expense_charge_cost_center
AFTER INSERT ON cost_bank FOR EACH ROW
WHEN (new.work_code in (select work_code from master_data where charge_type = 'EX'))
BEGIN
update cost_bank set cost_center = (select r_cost_center
from master_data where work_code = new.work_code) where id = new.id;
END;
Any insight is appreciated
If you want to modify the same table, you want a before insert trigger:
CREATE OR REPLACE TRIGGER expense_charge_cost_center
BEFORE INSERT ON cost_bank FOR EACH ROW
WHEN (new.work_code in (select work_code from master_data where charge_type = 'EX'))
BEGIN
select r_cost_center into :new.cost_center
from master_data
where work_code = new.work_code;
END;
Actually, I'm not sure if subqueries work with when, so you might need:
CREATE OR REPLACE TRIGGER expense_charge_cost_center
BEFORE INSERT ON cost_bank FOR EACH ROW
BEGIN
if (new.work_code in (select work_code from master_data where charge_type = 'EX')) then
select r_cost_center into :new.cost_center
from master_data
where work_code = new.work_code; -- I'm guessing you also want charge_type = 'EX'
end if;
END;

Writing a trigger for AFER Update on DB2

I want to set the column EDI_INVOICE to False whenever the DOCUMENT_TYPE is a REBILL for only specific BILL_TO_CODES
This is how I wrote my trigger
CREATE TRIGGER BT_CU_CASS_REBILLS
AFTER UPDATE OF DOCUMENT_TYPE ON TLORDER
REFERENCING OLD AS O NEW AS N
FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
IF N.DOCUMENT_TYPE <> O.DOCUMENT_TYPE AND N.DOCUMENT_TYPE = 'REBILL'
AND N.BILL_TO_CODE IN (SELECT TRADING_PARTNER FROM EDI_PROFILES WHERE EDI_TYPE = '210' AND EDI_ACTIVE = 'True' AND UPPER(FTP_ADDRESS) LIKE '%CASS%')
THEN SET N.EDI_INVOICE = 'True';
END IF;
END
But when trying to execute the Query to create the trigger I get this Error
SQL0797N The Trigger Lynx.BT_CU_CASS_REBILLS is defined with an unsporrted triggered SQL statement. Line Number = 11. SQLSTATE = 42987
Thank you in advance.
If you want the trigger to change the data in the row for which the trigger is firing, ie.
THEN SET N.EDI_INVOICE = 'True';
you need to use a BEFORE UPDATE trigger.

Trigger function updates all rows instead of one (PostgreSQL)

Using PostgreSQL.
What I have is:
3 tables
1.Customer2c with columns: CustomerID,PersonID,Number_Of_Items`.
2.SalesOrderHeader2c with columns: SalesOrderID,CustomerID.
SalesOrderDetail2c with columns: SalesOrderDetailID,SalesOrderID,OrderQty
I want to create a trigger function, that will trigger whenever someone uses
INSERT INTO 'SalesOrderDetail2c' table
and that is going to get the OrderQty that was inserted and update the correspondent Number_Of_Items field with it.
My trigger is working, but the problem is that whenever I insert a new value to the SalesOrderDetail2c, the function gets the OrderQty value and updates all the rows of Number_Of_Items with it, instead of updating just the correspondent one.
Any help appreciated. What I have so far is this (It may be copletely wrong, dont judge please!):
CREATE OR REPLACE FUNCTION FunctionTrigger2c() RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE Customer2c
SET Number_Of_Items =
(SELECT OrderQty
FROM SalesOrderDetail2c
INNER JOIN SalesOrderHeader2c ON (SalesOrderDetail2c.SalesOrderID = SalesOrderHeader2c.SalesOrderID)
INNER JOIN Customer2c ON (SalesOrderHeader2c.CustomerID = Customer2c.CustomerID)
ORDER BY SalesOrderDetailID DESC LIMIT 1
)
FROM SalesOrderHeader2c
WHERE SalesOrderHeader2c.CustomerID = Customer2c.CustomerID
;
RETURN NEW;
END;
$BODY$
language plpgsql;
CREATE TRIGGER Trigger2c
AFTER INSERT ON SalesOrderDetail2c
FOR EACH ROW
EXECUTE PROCEDURE FunctionTrigger2c();
I had to use .new as #Nicarus mentioned above! Thanks again by the way.
This is the new code and now it changes only the correspondent value.
CREATE OR REPLACE FUNCTION FunctionTrigger2c() RETURNS TRIGGER AS
$BODY$
BEGIN
UPDATE Customer2c
SET Number_Of_Items =
(SELECT new.OrderQty
FROM SalesOrderDetail2c
order by salesorderdetailid desc limit 1
)
FROM SalesOrderheader2c
WHERE (SalesOrderheader2c.salesorderID = new.salesorderID) and (salesorderheader2c.customerid = customer2c.customerid)
;
RETURN NEW;
END;
$BODY$
language plpgsql;
CREATE TRIGGER Trigger2c
AFTER INSERT ON SalesOrderDetail2c
FOR EACH ROW
EXECUTE PROCEDURE FunctionTrigger2c();
I am pointing out why your original trigger did not work. The reason it updated every row is because of your UPDATE statement. After you inserted something, it triggered the update.
When the update ran it got these things:
What table I am gonna update
What value am I gonna set on what column of the given table
What rows I am gonna implement this update on (FROM + WHERE)
The problem lies in the last part, basically calling FROM in an UPDATE statement is like calling a SELECT statement, it tried to process every row from the FROM clause tables with the given WHERE value.
PostgreSQL documentation about UPDATE statement from_list parameter states that "A
list of table expressions, allowing columns from other tables to
appear in the WHERE condition and the update expressions. This is
similar to the list of tables that can be specified in the FROM Clause
of a SELECT statement."
(https://www.postgresql.org/docs/9.1/sql-update.html)
Basically, your update statement went through every row in SalesOrderHeader2c which conveniently matched with every row of Customer2c (with SalesOrderHeader2c.CustomerID = Customer2c.CustomerID), updating the value of every row in Customer2c with the firstly found Number_Of_Items value from the UPDATE SET statement. This is why you got the same value for every row in Customer2c.
The reason the new trigger works is because the update statement is done with the correctly selected rows.
Here is my, quite general trigger that is used do count/sum values in dependent tables. You should take care of all order changes, ie not only INSERT but also DELETE and UPDATE. You also should read #Nicarus comment about using NEW (and OLD) in triggers.
I have altered it to match your schema, but didn't test it...
CREATE OR REPLACE FUNCTION FunctionTrigger2c()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
CASE TG_OP
WHEN 'INSERT' THEN
UPDATE
Customer2c
SET
Number_Of_Items = Number_Of_Items + NEW.OrderQty
FROM
SalesOrderHeader2c
WHERE
Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND
SalesOrderHeader2c.SalesOrderID = NEW.SalesOrderID AND
SalesOrderDetailID = NEW.SalesOrderDetailID;
WHEN 'UPDATE' THEN
UPDATE
Customer2c
SET
Number_Of_Items = Number_Of_Items - OLD.OrderQty
FROM
SalesOrderHeader2c
WHERE
Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND
SalesOrderHeader2c.SalesOrderID = OLD.SalesOrderID AND
SalesOrderDetailID = OLD.SalesOrderDetailID;
UPDATE
Customer2c
SET
Number_Of_Items = Number_Of_Items + NEW.OrderQty
FROM
SalesOrderHeader2c
WHERE
Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND
SalesOrderHeader2c.SalesOrderID = NEW.SalesOrderID AND
SalesOrderDetailID = NEW.SalesOrderDetailID;
WHEN 'DELETE' THEN
UPDATE
Customer2c
SET
Number_Of_Items = Number_Of_Items - OLD.OrderQty
FROM
SalesOrderHeader2c
WHERE
Customer2c.CustomerID = SalesOrderHeader2c.CustomerID AND
SalesOrderHeader2c.SalesOrderID = OLD.SalesOrderID AND
SalesOrderDetailID = OLD.SalesOrderDetailID;
END CASE;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
UPDATE also work well if you change the SalesOrderID :)
Notice, that this trigger returns NULL and it should be set as AFTER INSERT OR UPDATE OR DELETE:
CREATE TRIGGER Trigger2c
AFTER INSERT OR UPDATE OR DELETE
ON SalesOrderDetail2c
FOR EACH ROW
EXECUTE PROCEDURE FunctionTrigger2c();

Oracle 11g Trigger Issue

I'm a newbie to database and trying to create a trigger which will change a char from "Y" to "N" if another table's tuple is set to 0. I have it working somewhat but it is changing all tuples instead of the single one I want. Here is the trigger and code. Any suggestions gratefully received.
create or replace TRIGGER CHANGE_STOCK_FLAG
AFTER UPDATE OF AMOUNT_REMAINING ON PRODUCT
FOR EACH ROW
BEGIN
UPDATE BOOK
SET IN_STOCK = 'N';
END;
Update statement:
UPDATE PRODUCT
SET AMOUNT_REMAINING = 0
WHERE PROD_ID = 5001;
The trigger compiled OK and on update above resets IN_STOCK to "N" on all tuples in the Book TABLE.
Is there a where clause or something I can use?
Try this:
CREATE OR REPLACE TRIGGER CHANGE_STOCK_FLAG
AFTER UPDATE OF AMOUNT_REMAINING ON PRODUCT
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF (:NEW.AMOUNT_REMAINING=0) THEN
UPDATE BOOK SET IN_STOCK = 'N' WHERE PROD_ID=:NEW.PROD_ID;
END IF;
END;

Why this trigger doesn't compile(oracle)?

Error: SQL Statement ignored (underline UPDATE TABLE)
CREATE OR REPLACE TRIGGER CANCEL_TICKET
AFTER INSERT ON CANCEL
FOR EACH ROW
BEGIN
UPDATE TABLE TICKET
SET TICKET.TICKET_ID := NULL
WHERE TICKET.TICKET_ID = :NEW.TICKET_ID;
END;
there is no need for TABLE and a colon : is more in your statement, so better
UPDATE TICKET
SET TICKET.TICKET_ID = NULL