Need Guidance with writing MySQL Trigger - mysql

I'll admit, up front, that this is my first MySQL trigger. The MySQL version is 8.0.
I have a table for orders and order line items. In the orders table I have a column that stores the total of all line items. I need a trigger that updates that total every time a line items is added or changed for that order. Here's what I have so far:
CREATE TRIGGER update_line_item_total
AFTER INSERT
ON orderlines.price FOR EACH ROW
BEGIN
-- variable declarations
DECLARE li_order_id INT;
DECLARE li_total DEC;
SET li_order_id = orderlines.order_id;
SET li_total = SUM (orderlines.price) WHERE orderlines.order_id = li_order_id;
-- trigger code
UPDATE orders SET
total_lineitems = li_total
WHERE orders.order_id = li_order_id;
END;
I put this into MySQL Workbench and it was rejected. I know that the DECLARE statements, the 2nd SET statement, and the END statements were the ones flagged as incorrect, however I'm not even sure where to look to find out what's wrong.
Looking for guidance and direction.
Thanks,
Michael Frankel
Wizard Consulting Group, Inc.

your problem is on this line : SET li_total = SUM (orderlines.price) WHERE orderlines.order_id = li_order_id;
add delimiters.
do this :
delimiter |
CREATE TRIGGER update_line_item_total
AFTER INSERT
ON orderlines.price FOR EACH ROW
BEGIN
-- variable declarations
DECLARE li_order_id INT;
DECLARE li_total DEC;
declare li_total_temp dec;
SET li_order_id = orderlines.order_id;
select orderlines.price into li_total_temp WHERE orderlines.order_id = li_order_id;
SET li_total = li_total + li_total_temp;
-- trigger code
UPDATE orders SET
total_lineitems = li_total
WHERE orders.order_id = li_order_id;
END |
delimiter ;

Related

MySQL stored procedure with no parameters can't recognize datatypes

can You help.
This code should update quantity of product in packages to by equal to minimum stock of product that are forming the package. My stocks are updated based on data form Oracle ERP every 5 minutes, but ERP does not know abort packages - they exists only in Prestashop, and they have to be updated independently in cycles (job). I try to do it by procedure.
CREATE OR REPLACE PROCEDURE B2C_P_QUANTYTY_UPDATE
BEGIN
FOR i IN
(SELECT ps_pack.id_product_pack, min(ps_stock_available.quantity) min_quantity
FROM ps_pack, ps_stock_available
WHERE ps_pack.id_product_item = ps_stock_available.id_product
GROUP BY ps_pack.id_product_pack)
LOOP
UPDATE ps_stock_available
SET ps_stock_available.quantity = i.min_quantity
WHERE ps_stock_available.id_product = i.id_product_pack ;
END LOOP ;
END;
2 errors has been found in analysis.
Unrecognized data type. (near "ps_pack" at position 81)
Unrecognized data type. (near "(" at position 109)
MySQL returned:
#1064 - Something is wrong in your syntax near 'BEGIN
FOR i IN
(SELECT ps_pack.id_product_pack, min(ps_stock_available.qua' in line 2
I don't understand why, the select query works fine. But wrapped inside procedure stops recognizing data types.
Thanks to #Barranka answer to post SQL - Looping through ever row of table in mysql? i was able to do it.
And the code looks like that:
DELIMITER $$
CREATE OR REPLACE PROCEDURE B2C_P_QUANTYTY_UPDATE ()
BEGIN
DECLARE c_product int;
DECLARE c_min_quantity int;
DECLARE done int default false;
DECLARE quantity_cursor cursor FOR SELECT ps_pack.id_product_pack AS product , MIN(ps_stock_available.quantity) min_quantity
FROM ps_pack, ps_stock_available
WHERE ps_pack.id_product_item = ps_stock_available.id_product
GROUP BY ps_pack.id_product_pack;
DECLARE continue handler FOR not found
SET done = true;
OPEN quantity_cursor;
quantity_loop: LOOP
FETCH quantity_cursor INTO c_product, c_min_quantity;
IF done THEN
leave quantity_loop;
END IF;
UPDATE ps_stock_available
SET ps_stock_available.quantity = c_min_quantity
WHERE ps_stock_available.id_product = c_product;
END loop ;
CLOSE quantity_cursor;
COMMIT;
END$$
DELIMITER ;

MySql trigger not works

I have 3 tables
tbl_payments(pay_id,date,amount,description,-------)
tbl_pay_trans(pay_id,trans_id)
tbl_transactions(trans_id,trans_date,trans_amount,trans_description,-----)
'tbl_transaction' has the same data from the 'tbl_payments' along with some other values. To maintain the relationship between the two tables I use 'tbl_pay_trans'. What I want to do is, when an update done on tbl_payments(amount,description) the same changes need to do in tbl_transactions(trans_amount,trans_description). I wrote a trigger to do that, but it dose not update the tbl_transaction table values as it supposed to.
My trigger is
DELIMITER $$
CREATE TRIGGER update_trans
AFTER UPDATE on tbl_payments
FOR EACH ROW
BEGIN
DECLARE new_amount VARCHAR(50);
DECLARE new_description TEXT;
DECLARE new_pay_id,new_trans_id INT;
SET new_pay_id = OLD.pay_id;
SET new_amount = OLD.amount;
SET new_description = OLD.description;
SELECT trans_id INTO new_trans_id FROM tbl_pay_trans WHERE pay_id = new_pay_id;
UPDATE tbl_transactions SET
trans_amount = new_amount,
trans_description = new_description
WHERE trans_id = new_trans_id;
END$$
DELIMITER ;
Please someone help me to figure out what I did wrong.
It's not updating because you are using OLD on the amount and description columns where you need to use NEW i.e.
SET new_amount = NEW.amount;
SET new_description = NEW.description;
OLD refers to the column value before the update occurred in tbl_payments. See the manual.

Copy one column to another, two seperate tables

I want to copy all values from one column in table A to another column in table B. The column has 100+ rows. I tried this:
UPDATE nds_product_lang pl
SET description_short = (
SELECT product_supplier_reference
FROM nds_product_supplier ps
WHERE ps.id_product = pl.id_product);
But what it returns is
#1242 - Subquery returns more than 1 row
It returns the same error even if I remove the WHERE condition. What am I doing wrong?
Try this
UPDATE nds_product_lang pl, nds_product_supplier ps
SET pl.description_short = ps.product_supplier_reference
WHERE ps.id_product = pl.id_product
You can use a store procedure:
See below example
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `additem`()
BEGIN
declare no_record int default 0;
declare mycat varchar(45) default ''; //variable data destination
declare mycursor CURSOR FOR // this point your source table
select field-name FROM yourtable;
declare continue handler for not found
set no_record = 1;
open mycursor;
add_item: LOOP
FETCH mycursor INTO mycat;
IF no_record = 1 THEN
LEAVE add_item;
END IF;
-- build email list
insert into dest_table values(val-field1,mycat, ect..);
END LOOP add_item;
close mycursor;
this work perfectly :-)

Trigger Loop keeps putting currentStock on 0

So I'm trying to work out a trigger that automatically adds the ingredients from a order (dhh_purchaseorder) to the table dhh_ingredients. It should get the new ordered amount out of dhh_purchaseorderingredient and dump it into the orderAmount variable. Then it should combine the current available stock with the ordered amount in newStock. Then it should update the ingredient table and set the new amounts for the correct ingredients but for some reason it keeps putting the currentStock column in ingredients to 0.
Here is my trigger:
BEGIN
DECLARE orderStatus, orderIngredientName VARCHAR(50);
DECLARE finished INTEGER DEFAULT 0;
DECLARE currentStock, newStock DECIMAL(10,2);
DECLARE orderNo, orderAmount int(10);
DECLARE lookupCursor CURSOR FOR SELECT INGREDIENTingredientName from dhh_purchaseorderingredient WHERE dhh_purchaseorderingredient.PURCHASEpurchaseOrderNo = NEW.purchaseOrderNo;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
SET orderNo = NEW.purchaseOrderNo;
SET orderStatus = NEW.status;
IF(orderStatus = "DELIVERED") THEN
OPEN lookupCursor;
update_loop: LOOP
FETCH lookupCursor INTO orderIngredientName;
IF finished = 1 THEN
LEAVE update_loop;
END IF;
SET orderAmount = (SELECT amount from dhh_purchaseorderingredient WHERE dhh_purchaseorderingredient.PURCHASEpurchaseOrderNo = orderNo AND dhh_purchaseorderingredient.INGREDIENTingredientName = orderIngredientName);
SET currentStock = (SELECT currentStock FROM dhh_ingredient WHERE ingredientName = orderIngredientName);
SET newStock = currentStock + orderAmount;
INSERT INTO temp VALUES(currentStock);
UPDATE dhh_ingredient
SET currentStock = newStock
WHERE ingredientName = ingredientName;
END LOOP update_loop;
CLOSE lookupCursor;
END IF;
END
This is partly an answer and partly a suggestion for a better approach.
One of the many reasons I believe stored procedures are a very bad idea is that they are hard to debug. In this case, it's not easy to figure out what value is being assigned to the various stock amount variables.
A better approach is to use query that does update - without the need for SP variable. It's really easy to test it; just execute and inspect the results. By using such a query in your SP, you eliminate incorrect query logic from your code, allowing you to condense the SP to just the bits that matter - the update.
Fortunately, MySQL provides a way to update through a join, via its multi-table update syntax.
This is what the query could look like:
UPDATE dhh_ingredient, dhh_purchaseorderingredient
SET = currentStock = currentStock - amount
WHERE dhh_purchaseorderingredient.INGREDIENTingredientName = orderIngredientName
AND ingredientName = orderIngredientName
AND dhh_purchaseorderingredient.PURCHASEpurchaseOrderNo = NEW.purchaseOrderNo
AND NEW.status = 'DELIVERED';
No need for local variables or any loops, because the update query does a join and the NEW values are used directly in the query.
So your entire stored procedure becomes simply:
BEGIN
UPDATE dhh_ingredient, dhh_purchaseorderingredient
SET = currentStock = currentStock - amount
WHERE dhh_purchaseorderingredient.INGREDIENTingredientName = orderIngredientName
AND ingredientName = orderIngredientName
AND dhh_purchaseorderingredient.PURCHASEpurchaseOrderNo = NEW.purchaseOrderNo
AND NEW.status = 'DELIVERED';
END
which is easy to understand, maintain and debug - a better solution.

Assigning the value from a select statement to a vairable in MySQL

I'm fairly new to SQL in general and even more so to MySQL and I've hit a stumbling block. I'm attempting to use a procedure to copy the value of one field to another if the original field is not null, this procedure is then called by triggers whenever the table is updated or has a new row inserted into it. Here is what I have so far:
-- WORK_NOTES_PROCEDURE - This copies the contents of the estimate notes to the work order notes if the original estimate had any notes with it.
DROP PROCEDURE IF EXISTS 'WORK_NOTES_PROCEDURE';
DELIMITER $$
CREATE PROCEDURE WORK_NOTES_PROCEDURE()
BEGIN
DECLARE var_temp VARCHAR(50);
SET var_temp := (SELECT ESTIMATE_NOTES FROM ESTIMATES WHERE ESTIMATES.ESTIMATE_NUMBER = WORK_ORDERS.ESTIMATE_NUMBER);
IF var_temp IS NOT NULL THEN
UPDATE WORK_ORDERS SET WORK_ORDER_NOTES = var_temp WHERE WORK_ORDERS.ESTIMATE NUMBER = ESTIMATES.ESTIMATE_NUMBER;
END IF;
END$$
DELIMITER ;
Absolutely any help would be appreciated, the error I'm getting is a syntax error for the line where I'm assigning a value to var_temp.
try,
SET var_temp = (SELECT ESTIMATE_NOTES
FROM ESTIMATES INNER JOIN WORK_ORDERS
ON ESTIMATES.ESTIMATE_NUMBER = WORK_ORDERS.ESTIMATE_NUMBER
LIMIT 1);