Moving MySQL trigger to DB2; issue with keyword NEW - mysql

I have this trigger working in MySQL:
CREATE TRIGGER Recharge_trigger
AFTER INSERT ON Recharges
FOR EACH ROW
UPDATE Balances
SET Balance = Balance + NEW.Amount
Where Uid = NEW.Uid AND Stid = NEW.Stid;
It automatically updates the balance column in the Balances table whenever I insert a row in the Recharges table.
However when I tried to run it in DB2, it's giving this error:
Server Error: Error for batch element #1: "NEW.AMOUNT" is not valid in the context where it is used.. SQLCODE=-206, SQLSTATE=42703, DRIVER=3.66.46
I think it's the keyword NEW that's messing it up. Is there any way I can write this in DB2?

I don't have access to any DB2 database so I couldn't test it but looking at the documentation I think you need to include a REFERENCING clause. Try this instead:
CREATE TRIGGER Recharge_trigger
AFTER INSERT ON Recharges
REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
UPDATE Balances SET Balance = Balance + N.Amount Where Uid = N.Uid AND Stid = N.Stid;
END

Related

How to execute the Data in chunks or Batch wise in loop using MYSQL

I have table which have 20 million records . I have recently added another column to that table.
I need to update the data into that column.
I'm using MYSQL community edition, when I execute the direct update like this :
Update Employee SET Emp_mail = 'xyz_123#gmail.com'
System Getting hanged and Need to close the execution abruptly.
But when I update the statement with filter condition it is executing fine.
Update Employee SET Emp_mail = 'xyz_123#gmail.com' where ID <= 10000;
Update Employee SET Emp_mail = 'xyz_123#gmail.com' where ID >= 10000 AND ID <= 10000 ;
--------
--------
no of Times
Now I'm looking for looping script where I can execute in chunk wise.
For example in SQL it is like this but I'm not sure of MYSQL:
BEGIN
I int = 0 ;
cnt = 0 ;
while 1 > cnt
SET i = i + 1;
Update Employee SET Emp_mail = 'xyz_123#gmail.com' where ID >= cnt AND ID <= I
END
Note : this is a random script syntax wise there may be some errors . Please ignore it.
I'm looking for Looping in MYSQL
In a row based database system as MySQL, if you need to update each and every row, you should really explore a different approach:
ALTER TABLE original_table RENAME TO original_table_dropme;
CREATE TABLE original_table LIKE original_table_dropme;
ALTER TABLE original_table ADD emp_mail VARCHAR(128);
INSERT INTO original_table SELECT *,'xyz_123#gmail.com'
FROM original_table_dropme;
Then, maybe keep the original table for a while - especially to transfer any constraints, primary keys and grants from the old table to the new - and finally drop the %_dropme table.
Each update, in a row based database, of a previously empty column to a value, will make each row longer than it originally was, and require a reorganisation, internally. If you do that with millions of rows, the effort needed will increase exponentially.

MySql - can AFTER INSERT trigger delete the row which invoked it

Let me put it in simplest words possible - is it possible to delete the row, which actually set On the trigger i.e. I have an AFTER INSERT ON <table2> trigger, the SQL in the trigger INSERT / UPDATE another <table1> (based on a WHERE), and finally tends to delete the entry/row in the (the row which basically fired the trigger).
Trigger SQL:
DELIMITER ||
DROP TRIGGER IF EXISTS trg_adddata_tmp ||
CREATE TRIGGER trg_adddata_tmp
AFTER INSERT ON adddata_tmp
FOR EACH ROW
BEGIN
IF EXISTS (SELECT * FROM adddata WHERE data_id = new.data_id AND account_name = new.account_name) THEN
UPDATE adddata SET data_id = new.data_id, account_name = new.account_name, user_name = new.user_name, first_name = new.first_name, last_name = new.last_name WHERE data_id = new.data_id AND account_name = new.account_name;
ELSE
INSERT INTO adddata (data_id, account_name, user_name, first_name, last_name)
VALUES(new.data_id, new.account_name, new.user_name, new.first_name, new.last_name);
END IF;
DELETE FROM adddata_tmp WHERE id = new.id;
END;
||
Without the DELETE (just above the END;) the trigger works fine - UPDATE if exist otherwise INSERT - with DELETE statement gives the following error:
Error Code: 1442
Can't update table 'adddata_tmp' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
By the way, the error is pretty self-explanatory, but still wanted to make sure if this is possible - if not this way, may be some other way around i.e. I want the adddata_tmp table to be empty (or clean-ed up) all the time (on INSERT copies the data to main adddata table)
One idea, I have in mind is, to use an EVENT to clean-up the adddata_tmp based on some status field - which gets set as the last statement in the trigger (in place of DELETE).
No, you can't do this with trigger, here's what the documentation says:
A stored function or trigger cannot modify a table that is already
being used (for reading or writing) by the statement that invoked the
function or trigger.
If adddata_tmp table needs to be empty all the time then I would not write trigger at all. Instead, I would recommend moving adddata update logic in the script/service that tries to insert the data into adddata_tmp.
update
If we are doing bulk inserts and the data (in adddata_tmp table) is not utilised anywhere else then we can write a cron job to clean up the table (i.e. the one that executes let's say every 10 minutes). Also, TRUNCATE would be more efficient (than DELETE) in this case.

SQL Trigger - Update table A with sum(tableB.col) WHERE tableA.userID = tableB.userID

I'm a pretty new database student...
I have two tables. User, and Trip.
Whenever a new Trip is added to the database, I want it to trigger an update on the User table in the "totalMiles" column. I want it to take the Trip.userID and change the value in the "totalMiles" column of only the user with the same User.userID as the Trip.userID entry.
I want it to take the sum from "tripMiles" where the Trip.userID = User.userID. userID is a foreign key in the Trip table from the User table.
right now I just have:
CREATE DEFINER='root'#'localhost'TRIGGER 'DATABASE'.'Trip_AFTER_INSERT'
AFTER INSERT ON 'Trip' FOR EACH ROW
BEGIN
UPDATE User
SET totalMiles=sum(tripMiles)
WHERE Trip.userID = User.userID;
END
The error I get is "unknown column 'Trip.userID' in 'where clause'.
I googled and searched through a couple of posts here but I didn't really find anything.
Just change de "User.userID" on where clausule to "NEW.userID"
The "New" object means your new TRIP added...
Something like this:
CREATE TRIGGER 'Trip_AFTER_INSERT'
AFTER INSERT ON 'Trip' FOR EACH ROW
BEGIN
UPDATE User
SET totalMiles=sum(tripMiles)
WHERE User.userID = NEW.userID;
END
If you want more, see documentation here:
https://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html
and here
How to program a MySQL trigger to insert row into another table?
You have multiple problems with your statement, starting with the single quotes. One method is to recalculate the sum:
CREATE TRIGGER DATABASE.Trip_AFTER_INSERT
AFTER INSERT ON Trip FOR EACH ROW
BEGIN
UPDATE User u
SET totalMiles = (SELECT sum(t.tripMiles) FROM Trip t WHERE t.userId = u.userId)
WHERE u.userID = new.userID;
END;
The is overkill, though. If totalMiles is previously correct, then just adjust the value:
CREATE TRIGGER DATABASE.Trip_AFTER_INSERT
AFTER INSERT ON Trip FOR EACH ROW
BEGIN
UPDATE User u
SET totalMiles = u.totalMile + new.tripMiles - old.tripMailes;
WHERE u.userID = new.userID;
END;

PHPmyAdmin mySQL Trigger: Upddate the parent table when child table was inserted, updated or deleted

I need some help with getting the syntax right to define a trigger in PHPmyAdmin.
What I have:
2 tables - invoice and invoiceitem
tbl_invoice has a field 'Total' which should show the sum of the 'Extended' price of the table invoiceitem
tbl_invoiceitem has 2 triggers that update the 'Extended' before_insert and before_update
What I try to accomplish:
Calculate the sum of all items for an invoice and update the 'Total' price in tbl_invoice after either new items are inserted or if the price or quantity for an existing item was updated.
I try to do this in PHPmyAdmin.
The error message is
I hope somebody can give mt a hint into the right direction. Just started with triggers and don't seem to find solution with a couple of days searching the internet.
Thank you for help in advance.
Cheers, Oliver
I can see 2 syntax errors in your code:
The delimiter commands should be outside of the trigger definition, not inside of it. Phpmyadmin should take care of this.
The commands within the begin ... end block should be terminated by semicolon (;), not by whatever you provide in the delimiter command.
I did not check if your sql commands within the trigger make sense, but the where condition of the set command does not seem right.
Ok, found a work around:write the full create trigger statement in a file and import with PHPmyAdmin. As 'Shadow' pointed out there was also a problem in the where conditions.
Below the corrected triggers that worked in my scenario.
There is a lot of examples on the net to get triggers done with the mysql client. This way you can use the exact syntax that you would type into a client and than import into PHPmyAdmin in case you can't reach the server your using with a command shell client.
Hope this helps other newbies.
Cheers, Oliver
-- after_insert trigger for InvoiceItem to Calculate the Total in Invoice
------------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Insert` AFTER INSERT ON `invoiceItem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = NEW.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-- after_update trigger for InvoiceItem to Calculate the Total in Invoice
------------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Update` AFTER UPDATE ON `invoiceitem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = NEW.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-- after_delete trigger for InvoiceItem to Calculate the Total in Invoice
----------------------------------------------------------------------
DELIMITER //
CREATE TRIGGER `InvoiceItem_After_Delete` AFTER DELETE ON `invoiceItem`
FOR EACH ROW
BEGIN
SET #InvoiceNumber = OLD.InvoiceFK;
SET #ItemTotal = (SELECT SUM(Extended) FROM InvoiceItem WHERE InvoiceFk = #InvoiceNumber);
UPDATE Invoice SET Total = #ItemTotal WHERE id = #InvoiceNumber;
END
//
DELIMITER ;
-----------------------------------------------------------------
The next 2 triggers are just single statement and are calculate the 'Extended' column in the InvoceItem table
---------------------------------------------------------------------
-- Calculate new 'Extended' price before insert
CREATE TRIGGER `InvoiceItem_Before_Insert` BEFORE INSERT ON `invoiceitem`
SET NEW.Extended = ROUND(NEW.Quantity * NEW.Price,2)
-------------------------------------------------------------------
-- Calculate new 'Extended' price before update
CREATE TRIGGER `InvoiceItem_Before_Update` BEFORE UPDATE ON `InvoiceItem`
FOR EACH ROW
SET NEW.Extended = ROUND(NEW.Quantity * NEW.Price,2);

MySQL Procedure - Assign calculation on columns within an update to a variable to be used in another update

I have a database with 3 tables and I am updating a row in the first, and then trying to update the second and third tables based on the change to a field in the first.
Here is what I have at present:
--Session--
User Hotspot DownloadCounter
bob 123 0
--UserDownload--
User Download
bob 100
--HotspotDownload--
Hotspot Download
123 300
Currently when I get an update from the hotspot I update the session table with the latest traffic counter value, however I would now like to update the UserDownload & HotspotDownload tables with the value of the new DownloadCounter - the old DownloadCounter.
I thought this would be easy with the following procedure:
DECLARE increment INT;
UPDATE Session
SET #increment = (200 - Counter),
Counter = 200
WHERE (User = 'bob' AND Circuit = '123');
UPDATE UserDownload
SET Total = (Total + #increment)
WHERE (User = 'bob');
UPDATE HotspotDownload
SET Total = (Total + #increment)
WHERE (Circuit = '123');
The idea being I update the Session table and assign the counter change value to a variable which is then used in the update of the Download tables. But the '#' causes a syntax error in the procedure, and without the '#' it thinks increment is a column so fails.
If there are not entries for the user/hotspot in the total tables I still need to update the sessions table.
I tried doing this with a single update and a left join, but that resulted in the Sessions table column being updated first and so then the Download tables would not be updated.
Is it possible to assign the result of a calculation on columns to a variable within an update, and then use that update within another update in the procedure?
Thanks.
OK, looks like the way to do this is triggers.
Have the procedure just update the Session table, and then have a trigger against the table which runs before the actual update and updates the 2nd and 3rd tables.