I'm getting an error when trying to declare a new stored function in MySQL (Server version: 5.5.13)
Basically, I have a large table which classifies strings depending on how they start. My function takes a string (from user input) and then tells you the classification of that string by searching the database for the classification. It's a bit like a LIKE query, except in reverse as it's the user input that contains the full string and the database contains the string being searched for. Hope that makes sense!
The concept and logic behind it work fine as I've written/developed this in PHP and it works beautifully, however when trying to translate this into a stored function I'm getting an error from MySQL. The code of the function is:
delimiter $
DROP FUNCTION IF EXISTS get_string_class$
CREATE FUNCTION get_string_class(mystring VARCHAR(15))
RETURNS VARCHAR(15)
READS SQL DATA
BEGIN
DECLARE i INT;
SET i = 2;
DECLARE mystringlength INT;
SET mystringlength = LENGTH(mystring);
DECLARE segment VARCHAR(15);
DECLARE String_Class VARCHAR(15);
SET String_Class = NULL;
WHILE i <= mystringlength DO
SET segment = LEFT(mystring, i);
SET String_Class = (SELECT String_Class FROM string_class_list WHERE String_Begins = segment);
IF SELECT FOUND_ROWS() = 1 THEN
RETURN String_Class
END IF;
i = i + 1;
END WHILE;
RETURN String_Class;
END$
delimiter ;
I'm getting this error:
#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
'DECLARE mystringlength INT; SET mystringlength = LENGTH(mystring);
DECLARE segm' at line 10
I've done lots of playing around to trying and work out where I'm going wrong. I've even stripped out the loop altogether to test it, but still get the same error. Does anyone know what I've done wrong where declaring that INT variable? It's probably something incredibly basic...!
Thanks very much in advance.
There were some syntax errors -
One of them is - all declarations must be at the begining of the BEGIN...END clause.
DELIMITER $
DROP FUNCTION IF EXISTS get_string_class$
CREATE FUNCTION get_string_class(mystring VARCHAR(15))
RETURNS VARCHAR(15)
READS SQL DATA
BEGIN
DECLARE i INT;
DECLARE segment VARCHAR(15);
DECLARE String_Class VARCHAR(15);
DECLARE mystringlength INT;
SET i = 2;
SET mystringlength = LENGTH(mystring);
SET String_Class = NULL;
WHILE i <= mystringlength DO
SET segment = LEFT(mystring, i);
SET String_Class = (SELECT String_Class FROM string_class_list WHERE String_Begins = segment);
IF (SELECT FOUND_ROWS()) = 1 THEN
RETURN String_Class;
END IF;
SET i = i + 1;
END WHILE;
RETURN String_Class;
END$
DELIMITER ;
DECLARE part inside stored procedure must be at top and SET and other statemnts starts after that.
Related
I try to update some columns using trigger before insert
DROP TRIGGER IF EXISTS update_p_posts_places;
DELIMITER $$
CREATE TRIGGER update_p_posts_places BEFORE
INSERT
ON
`p_posts` FOR EACH ROW
BEGIN
DECLARE
p_post_group_id_ int;
SELECT
`p_post_subgroup`.`p_post_group_id`
INTO
p_post_group_id_
FROM
`p_post_subgroup`
WHERE
`p_post_subgroup`.`p_post_subgroup_id` = NEW.p_post_subgroup_id;
IF(p_post_group_id_ = 5) THEN
BEGIN
DECLARE
place1_id_ int;
place2_id_ int;
place3_id_ int;
place4_id_ int;
place5_id_ int;
SELECT
`Places`.`place1_id`,
`Places`.`place2_id`,
`Places`.`place3_id`,
`Places`.`place4_id`,
`Places`.`place5_id`
INTO
place1_id_, place2_id_, place3_id_, place4_id_, place5_id_
FROM
`Places`
WHERE
`Places`.`place5_id` = NEW.p_post_place_id LIMIT 1;
SET NEW.place5_id = place5_id_;
SET NEW.place1_id = place1_id_;
SET NEW.place2_id = place2_id_;
SET NEW.place3_id = place3_id_;
SET NEW.place4_id = place4_id_;
END $$
ELSE
SET NEW.place5_id = NULL;
END IF;
END $$
DELIMITER ;
It's showing some syntax errors.
#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 'DECLARE
place1_id_ int;
place2_id_ int;
' at line 20
Here is a working trigger. I tested creating it on MySQL 5.7.
CREATE TRIGGER update_p_posts_places BEFORE INSERT ON `p_posts`
FOR EACH ROW
BEGIN
-- all declarations must be before any other statements
DECLARE p_post_group_id_, place1_id_, place2_id_, place3_id_,
place4_id_, place5_id_ int;
SELECT
`p_post_subgroup`.`p_post_group_id`
INTO
p_post_group_id_
FROM
`p_post_subgroup`
WHERE
`p_post_subgroup`.`p_post_subgroup_id` = NEW.p_post_subgroup_id;
IF(p_post_group_id_ = 5) THEN
SELECT
`Places`.`place1_id`,
`Places`.`place2_id`,
`Places`.`place3_id`,
`Places`.`place4_id`,
`Places`.`place5_id`
INTO
place1_id_, place2_id_, place3_id_, place4_id_, place5_id_
FROM
`Places`
WHERE
`Places`.`place5_id` = NEW.p_post_place_id LIMIT 1;
SET NEW.place5_id = place5_id_;
SET NEW.place1_id = place1_id_;
SET NEW.place2_id = place2_id_;
SET NEW.place3_id = place3_id_;
SET NEW.place4_id = place4_id_;
ELSE
SET NEW.place5_id = NULL;
END IF;
END $$
You can use one DECLARE for multiple local variables, but you must do like var1, var2, var3, ... int. In other words, name the type only once at the end. See documentation: https://dev.mysql.com/doc/refman/8.0/en/declare-local-variable.html
No need for the BEGIN..END inside the IF and definitely do not use $$ until after the last END because that will terminate the parser's interpretation of your whole CREATE TRIGGER statement before it's complete.
I am trying to:
1. Print all the values in between #loop_start_date to #loop_end_date
2. loop_start_date should be increased by 1 here till loop_start_date=loop_end_date
I tried below but Mysql says
#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 'BEGIN Declare #user_id int' at line 3
Here is the procedure code
CREATE PROCEDURE generatePayscale
BEGIN
Declare #user_id int;
Declare #office_id int;
Declare #loop_start_date Date;
Declare #loop_end_date Date;
SET #user_id = 1287;
SET #office_id = 8;
SET #loop_start_date = '2018-06-02';
SET #loop_end_date = '2018-06-06';
WHILE(#loop_start_date < #loop_end_date) do
SELECT old_paysetupid
FROM personneltransfer personnelid=#user_id
AND pt.transferdate>#loop_start_date
END WHILE;
END
This may point you in the correct direction, a few things i would change. Added BEGIN. Then added declare for each of the vars. Then you need a where after the from
SET #user_id = 1287;
SET #office_id = 8;
SET #loop_start_date = '2018-06-02';
SET #loop_end_date = '2018-06-06';
WHILE(#loop_start_date < #loop_end_date) do
BEGIN
SELECT old_paysetupid
FROM personneltransfer where personnelid=#user_id
and pt.transferdate>#loop_start_date
END WHILE;
I am trying to use CURSOR inside mysql stored procedure... I am getting challenge while declaring the cursor... I error is **ERROR 1064 (42000): 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 ';
SELECT count(*) INTO countitem from TBL_SHOPPING_CART_ITEM
SELECT Produ' at line 8
**
Please help me to solve this issue... Thanks in advance.. my code is like below,
delimiter //
CREATE PROCEDURE placeOrder(IN cartId INT)
BEGIN
DECLARE countitem INT;
DECLARE productId INT;
DECLARE cartId INT;
DECLARE itemDicountAmt INT;
DECLARE itemCursor CURSOR;
SET countitem = SELECT count(*) from TBL_SHOPPING_CART_ITEM
SET itemCursor = SELECT ProductId, Quantity FROM TBL_SHOPPING_CART_ITEM
OPEN itemCursor
WHILE countitem > 0
BEGIN
FETCH itemCursor into productId, cartId;
itemDicountAmt = calculateNetItemStandardDiscountAmount(productId, cartId);
insert into debugtable select concat('item discount amount', itemDicountAmt);
SET countitem = countitem - 1;
END
CLOSE itemCursor
DEALLOCATE itemCursor
END//
delimiter ;
Don't worry, this isn't a bug.
The DECLARE clause is used to tell your machine that a local variable exists. The operations are made after the declarations, by aknowledging the existing, declared local variables.
So in your case, you tried to add a new declaration of variable after the machine started calculating, which isn't possible in MySQL. You'll have to find another way to use your last variable.
To assign a new content to a variable, first use DECLARE to create your variable first, then use SET as an assignment to the declared variable. I'll leave this link right here so you can get to know how to use it.
DELIMITER ##
create trigger tra_Price after update on assets_cdn_charge for each row
begin
declare res int;
declare ids int;
declare idq int;
declare idt int;
set res = (select price from assets_cdn_charge where price = new.price);
set ids = (select id from assets_cdn_charge where price = new.price);
DECLARE cur CURSOR FOR SELECT id FROM assets_cdn_composite WHERE cdn_charge_id = ids;
open cur;
ins_loop:LOOP
fetch cur into idq;
declare curs cursor for select id from assets_cdn_traffic where domain_name_id = idq;
open curs;
ins1_loop:LOOP
fetch curs into idt;
update assets_cdn_traffic set cost = traffic * res where domain_namd_id = idt;
end LOOP;
close curs;
end LOOP;
close cur;
END; ##
when I run this code,I had get this error:
ERROR 1064 (42000): 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 'DECLARE cur CURSOR FOR SELECT id FROM
assets_cdn_composite WHERE cdn_charge_id =' at line 9
Probably because:
DECLARE is permitted only inside a BEGIN ... END compound statement
and must be at its start, before any other statements.
...so that line should likely be moved before the two set statements above that point.
I believe that you're going to have other trouble if that fixes that error, because I don't know what you expect that query to retrieve as idq is declared before that point, but is not set to any value?
=====
UPDATE:
Below is an example from a previous comment about the possibility to eliminate cursors altogether. Try this:
BEGIN
UPDATE assets_cdn_traffic
JOIN assets_cdn_composite ON assets_cdn_traffic.domain_name_id = assets_cdn_composite.cdn_charge_id
JOIN assets_cdn_charge ON assets_cdn_charge.id = assets_cdn_composite.cdn_charge_id
SET cost = traffic * NEW.price
WHERE assets_cdn_charge.id = NEW.id
END
However, I would try the update query separately before using in the trigger to make sure that it works as expected. Replace the NEW.price and the NEW.id with test values to verify the handling.
DROP TRIGGER IF EXISTS `ACTUALIZAR_LOTE_DETALLE`;
DELIMITER //
CREATE TRIGGER `ACTUALIZAR_LOTE_DETALLE` AFTER INSERT ON `detalle_envio`
FOR EACH ROW BEGIN
DECLARE ID_INVENTARIO_IN INT;
DECLARE ID_LOTE_DETALLE_MIN INT;
DECLARE CANTIDAD_A_COMPARAR INT;
DECLARE CANTIDAD_A_RESTAR INT;
SET CANTIDAD_A_RESTAR = new.cantidad_enviado;
SET ID_INVENTARIO_IN = (Select id_inventario from detalle_requisicion WHERE id_detalle_requisicion = new.id_detalle_requisicion);
DECLARE cur_id CURSOR FOR SELECT id_lote_detalle from lote_detalle WHERE id_inventario = ID_INVENTARIO_IN AND cantidad > 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = 1;
OPEN cur_id;
read_loop: LOOP
FETCH cur_id INTO LOTE_DETALLE_IDS;
SET CANTIDAD_A_COMPARAR = select cantidad from lote_detalle where id_lote_detalle = LOTE_DETALLE_IDS;
IF CANTIDAD_A_RESTAR > CANTIDAD_A_COMPARAR THEN
UPDATE `lote_detalle` SET cantidad=cantidad-CANTIDAD_A_COMPARAR WHERE id_lote_detalle = LOTE_DETALLE_IDS;
SET CANTIDAD_A_RESTAR = CANTIDAD_A_RESTAR - CANTIDAD_A_COMPARAR;
ELSE
UPDATE `lote_detalle` SET cantidad=cantidad-CANTIDAD_A_RESTAR WHERE id_lote_detalle = LOTE_DETALLE_IDS;
LEAVE read_loop;
END IF;
IF DONE = 1 THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
CLOSE cur_id;
END
//
DELIMITER ;
Is anything in the cursor?
the query or something?
Is anything in the Syntax?
Cause i have based this Trigger from the syntax of the MySQL Forums
This is the Error:
#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 'DECLARE cur_id CURSOR FOR SELECT id_lote_detalle from lote_detalle WHERE id_inve' at line 9
There are at least following issues with your code:
All declarations should come before any statements (SET in your case). That's what is causing your immediate error.
You didn't declare DONE variable
You didn't declare LOTE_DETALLE_IDS variable, but you declared ID_LOTE_DETALLE_MIN which you didn't use. Perhaps you should rename ID_LOTE_DETALLE_MIN to LOTE_DETALLE_IDS then.
Since declarations go first you have to re-write your cursor definition (e.g. with subquery) because ID_INVENTARIO_IN variable isn't initialized yet
Your whole declaration section can be re-written in a following manner
-- declaration of variables of the same type can be combined
DECLARE ID_INVENTARIO_IN,
LOTE_DETALLE_IDS,
CANTIDAD_A_COMPARARINT,
CANTIDAD_A_RESTAR,
DONE INT;
DECLARE cur_id CURSOR FOR ...
DECLARE CONTINUE HANDLER ...
-- initialize variables
SET ...
Now, I believe your trigger most likely can be re-written with just update statement(s). You can get help with it if you explain in plain words what you're trying to achieve and provide exact table schemas and sample data.