Assigning the value from a select statement to a vairable in MySQL - 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);

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 ;

How to trigger the procedure for the sql database in system files

I have a table that holds a bunch of values for an order, I can do basic calculations on it until I get to a percentage. Right now I have my query as follows
declare #MyNumber decimal
set #MyNumber = (select SalesTax from [OrderHeader] where OrderHeaderID = 20)
select
sum(o.MaterialPrice) as "MatPrice",
sum(o.LaborPrice) as "LaborPrice",
sum(o.MaterialCost) as "MaterialCost",
sum(isnull(o.MaterialPrice,0)) - sum(isnull(o.MaterialCost,0)) - sum(isnull(o.LaborPrice,0)) * #MyNumber as "RESULT"
from [OrderDetail] o
inner join [OrderHeader] oh on oh.OrderHeaderID = o.OrderHeaderID
where o.OrderHeaderID = 20
PLEASE CHANGE AT LEAST NAZOV
DELIMITER $$
CREATE TRIGGER `nazov` BEFORE UPDATE
ON test
FOR EACH ROW BEGIN
SET NEW.OLD_TEXT=OLD.TEXT;
END $$
DELIMITER;

No-Data error in stored procedure

I am in the process of converting a SQL Server 2005 database to MySQL and having problems with a Stored procedure. I'm new to MySQL stored procedures so I'm sure it is a problem with my conversion but I'm not seeing it.
The stored procedure is supposed to generate a temporary table which is used to populate a Data Grid View in a vb.net application. However, I'm getting the error "Data No Data - Zero rows fetched, selected or processed.". Seems simple enough but the select procedure in the stored procedure will get data if I just run it as a query which is why I don't understand why the error.
I'm really hoping someone can tell me why because I have several hundred stored procedures to convert and I'm having this problem on the very first one.
Here's the Stored Procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `usp_get_unassigned_media`$$
CREATE DEFINER=`showxx`#`67.111.11.110` PROCEDURE `usp_get_unassigned_media`()
BEGIN
/* GET CURSOR WITH LOCAL LOCATIONS */
DECLARE intKey INT;
DECLARE dteDateInserted DATETIME;
DECLARE vchIdField VARCHAR(200);
DECLARE vchValueField VARCHAR(200);
DECLARE intLastKey INT;
/*TAKE OUT SPECIFIC PLAYLIST ITEMS IF TOO SLOW*/
DECLARE csrMediaToBeAssigned CURSOR FOR
SELECT
`media`.`key` AS `key`,
`media`.`date_inserted` AS `date_inserted`,
`media_detail_types`.`id` AS `id`,
`media_details`.`value` AS `value`
FROM (`media`
LEFT JOIN (`media_detail_types`
JOIN `media_details`
ON ((`media_detail_types`.`key` = `media_details`.`detail_key`)))
ON ((`media_details`.`media_key` = `media`.`key`)))
WHERE ((`media`.`is_assigned` = 0)
AND ((`media_detail_types`.`id` = 'Volume Name')
OR (`media_detail_types`.`id` = 'Drive Id')))
ORDER BY `media`.`key`,`media`.`date_inserted`,`media_detail_types`.`id`;
OPEN csrMediaToBeAssigned;
DROP TEMPORARY TABLE IF EXISTS temp_unassigned_media;
CREATE TEMPORARY TABLE temp_unnassigned_media
(temp_key INT, DateInserted DATETIME, IdField VARCHAR(200), ValueField VARCHAR (200))
ENGINE=MEMORY;
SET intLastKey = 0;
/*--GET FIRST RECORD */
FETCH FROM csrMediaToBeAssigned
INTO intKey, dteDateInserted, vchIdField, vchValueField;
/*--LOOP THROUGH CURSOR */
WHILE intLastKey = 0 DO
/*--DATA SHOULD BE IN DRIVE ID THEN VOLUME NAME */
INSERT INTO temp_unnassigned_media
VALUES (intKey, dteDateInserted, vchValueField, '');
FETCH NEXT FROM csrMediaToBeAssigned
INTO intKey, dteDateInserted, vchIdField, vchValueField;
UPDATE temp_unnassigned_media
SET IdField = vchValueField
WHERE temp_key = temp_key;
FETCH NEXT FROM csrMediaToBeAssigned
INTO intKey, dteDateInserted, vchIdField, vchValueField;
END WHILE;
SELECT *
FROM temp_unnassigned_media
ORDER BY date_inserted;
CLOSE csrMediaToBeAssigned;
/*DEALLOCATE csrMediaToBeAssigned */
/*DROP TABLE #temp_unnassigned_media */
END$$
DELIMITER ;
You never hit a condition where that WHILE loop will exit; you initialize intLastKey variable, but it never changes, so you fetch through the entire resultset. The exception is thrown when you fetch again, after the last record.
The normative pattern is to declare a CONTINUE HANDLER, which MySQL will execute when the NOT FOUND condition is triggered. The handler is normally used to set a variable, which you can then test, so you know when to exit the loop.
In your case, it looks like just adding this line, after your DECLARE CURSOR statement and before the OPEN statement, would be sufficient:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET intLastKey = 1;

Weird issue with a stored procedure in MySQL

I need to add a new stored procedure on our company's MySQL server. Since it's just slightly different, I used an already existing one, added the additional field and changed the name of the procedure. The weird thing now is that when I want to execute the statement, it returns:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
reffering to the 0 in this line: SET #update_id := 0; What makes it weird is, that I queried that stored procedure by using SHOW CREATE PROCEDURE . It's saved in our database and is working fine. I just can't use it as a new stored procedure (no matter if I try to apply it to the new test database or if I use it on the existing database by giving it a new name).
I searched the internet for a solution. Unfortunately to no avail. I even set up a new database with a new table and some demo values where I tried to execute the original, unaltered stored procedure. It returns the exact same error.
Here's the currently used and working stored procedure I'm talking about:
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
SET #update_id := 0;
UPDATE customer_shop SET state = 1, id = (SELECT #update_id := id), instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment WHERE tariff=Itariff AND state = 0 LIMIT 1;
SELECT * FROM customer_shop WHERE id = #update_id;
END
I hope you guys can help me as I am completely out of ideas what's wrong. :/
Regards, Mark
You need to define an alternative command delimiter, as MySQL currently thinks your CREATE PROCEDURE command ends at the first ; it encounters (on line 3, after the 0), which would be a syntax error as it's after a BEGIN but before the corresponding END:
DELIMITER ;; -- or anything else you like
CREATE PROCEDURE
...
END;; -- use the new delimiter you chose above here
DELIMITER ; -- reset to normal
MySQL stored procedures do not use ":=" for value assignment, just use "=".
Also don't think "id = (SELECT #update_id := id)" is acceptable. Here's an alternative solution (untested):
CREATE DEFINER=`root`#`localhost` PROCEDURE `customer_getcard`(IN Iinstance INT, IN Itimebuy DOUBLE, IN Iprice DECIMAL(10,2), IN Itariff INT, IN Icomment VARCHAR(128))
BEGIN
select id into #update_id from customer_shop WHERE tariff=Itariff AND state = 0 LIMIT 1;
UPDATE customer_shop SET state = 1, instance=Iinstance, timebuy=Itimebuy, price=Iprice, comment=Icomment where id = #update_id;
SELECT * FROM customer_shop WHERE id = #update_id;
END
You may also want to put error handlers in case there's no matching row to be edited.

MySQL: IF / THEN statements in stored procedures

I'm writing a stored procedure that uses multiple IF / THEN statements that also need to execute multiple queries if they evaluate to true. Problem is, I can't seem to find any examples of the appropriate syntax. From the MySQL dev handbook, it seems like I could have multiple queries in the "statement_list," but so far I can't get it to work.
Here's what I'm trying to do:
SET agency =
COALESCE((SELECT org_agency_o_id
FROM orgs_agencies
WHERE org_agency_code = maj_agency_cat)
,(SELECT min(org_id)
FROM orgs
WHERE org_name LIKE CONCAT('U.S.',SUBSTRING(maj_agency_cat,5))))
IF agency IS NULL THEN
-- execute multiple queries
INSERT INTO orgs (org_name
,org_name_length
,org_type
,org_sub_types)
VALUES (CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5))
,LENGTH(CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
,'org','Org,GovernmentEntity,Federal,Agency');
SET agency = LAST_INSERT_ID();
END IF;
The error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF agency IS NULL THEN
INSERT INTO orgs (org_name,org_name_length,org_type,' at line 53
Any ideas? I know it has to be something simple, so I would greatly appreciate anybody's input.
You got a few issues as far as I can see:
As David pointed out, each and every statement needs to be terminated by a ;
If you do a SELECT, better make sure it can only select one value by doing a LIMIT 1; If you've got an aggregate function like min() then only one value can come out.
If you writing the procedure using the CREATE PROCEDURE ... syntax, don't forget to set DELIMITER $$ before the CREATE PROCEDURE ... END $$ body and a DELIMITER ; after.
If you have multiple statements inside your IF THEN ... END IF block, it's a good idea to put them inside a BEGIN ... END; block.
If you have a return value, like agency here, why not make it a FUNCTION name (arg1: INTEGER) RETURNS INTEGER instead of a PROCEDURE name (IN arg1 INTEGER, OUT agency INTEGER). The function is much more versatile.
DELIMITER $$
CREATE PROCEDURE name(arg1 INTEGER, arg2 INTEGER, ...)
BEGIN
SELECT SET agency =
COALESCE((SELECT org_agency_o_id
FROM orgs_agencies
WHERE org_agency_code = maj_agency_cat) LIMIT 1,
(SELECT min(org_id) FROM orgs
WHERE org_name LIKE CONCAT('U.S.',SUBSTRING(maj_agency_cat,5))));
IF agency IS NULL THEN BEGIN
-- execute multiple queries
INSERT INTO orgs (org_name
,org_name_length
,org_type
,org_sub_types)
VALUES (CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5))
,LENGTH(CONCAT('U.S. ',SUBSTRING(maj_agency_cat,5)))
,'org','Org,GovernmentEntity,Federal,Agency');
SET agency = LAST_INSERT_ID();
END; END IF;
END $$
DELIMITER ;
No semicolon after your first SET statement.