Loops in stored procedures that won't execute - mysql

I've read many threads here about mysql loops that throw errors. So do mine but neither of the solutions I've tried seem to fix my problem.
I'm working with some stored procedures and I'm trying to get the following loop to work:
DECLARE counter INT(11) DEFAULT 0;
add_rows: LOOP
INSERT INTO vote_orders (id, vote_id, vote_order, vote_candidate)
WHILE counter <= #number_of_candidates DO
SELECT NULL, vote_id, counter, vote_candidate_a
FROM votes_copy
IF counter = #number_of_candidates THEN
LEAVE add_rows;
END IF;
UNION
END WHILE;
END LOOP add_rows;
This always throws the following 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 counter INT(11) DEFAULT 0;
add_rows: LOOP
INSERT INTO vote_orde' at line 30
I've tried to only store the declaration of 'counter' which seems to work perfect but as soon as I try to add the loop it fails. (#number_of_candidates is a stored procedure that's called from the loop, the UNION is supposed to union each selects until counter reaches #number_of_candidates).
Do you have any suggestions on why this won't work?

Related

Mysql Error when creating trigger

error note: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 '#sum int default 0;
set #sum=(select count(*) from inserted);
if #sum>1 then
' at line 5
and this is the code:
delimiter //
create trigger insert_only_one
after insert on sc
for each row
begin
declare #sum int default 0;
set #sum=(select count(*) from inserted);
if #sum>1 then
print('dont insert more than one record');
rollback transaction
end
The error note shows I have error at line 5.
I tried int(5) or just 'int', with or without default 0 still can't work.
You don't need to declare variable because you are using #sum variable that is initialized automatically..
you can't print anything inside a trigger...
Also your command rollback transaction is Invalid for MySQL.
Use only rollback with semicolon..

stored procedure is issuing syntax error

I am trying to create a mysql stored procedure with phpmyadmin:
CREATE PROCEDURE AddTableColumn()
BEGIN
IF (SELECT COUNT (table_name)
FROM information_schema.tables
WHERE table_name IN ('authors', 'publishers') = 2 )
print 'specified tables exist...';
ELSE
print 'specified tables unavailable...';
END IF;
END​
above code is a snippet that should search information schema
for the availability of authors and publishers tables,
then proceed to add new column in each table if present.
the print statement was for debug purpose. when i clicked the
GO command, here's the error message :
MySQL said:
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 'print 'avail...'; ELSE print 'unavail...'; END IF; END' at line
7.
what am i doing wrong ? i have even tried other code as a test,
all failing with the same error. code as simple as:
BEGIN
IF (6 > 4)
print 'greater';
ELSE
print 'lesser';
END IF;
END ​
all failed. any help will be appreciated.
'print' is not recognized in MySQL.
If you want to read back the output, just use a select in the SP.
Change part of your SP as below:
DECLARE found_status VARCHAR(255) DEFAULT NULL;
IF ....
SELECT 'specified tables exist...' INTO found_status;
ELSE
SELECT 'specified tables unavailable...' INTO found_status;
END IF;
SELECT found_status;

Creating a database function within Magento for a module

I have a working module in Magento that is modeled after some custom code we use outside of our install. This module currently add 5 tables to the database to store info and I have extended the Admin to CRUD the info. The ultimate goal here is to move the majority of this custom programming into Magento.
Currently our custom code sits outside Magento and hits a separate database. This database has those same 5 tables, a stored procedure, and 4 functions. What I would like to do now is move the stored procedures and the functions into Magento's database and change the custom code to call all of it's data from Magento's db. However, I can't seem to figure out how the "CREATE FUNCTION" call should be set up for Magento to execute it properly.
The SQL I am using is:
DROP FUNCTION IF EXISTS {$this->getTable('fn_Get_HardinessZone')};
CREATE FUNCTION {$this->getTable('fn_Get_HardinessZone')}(IN ZipCode varchar()) RETURNS integer AS
DECLARE Result integer;
BEGIN
SELECT MAX(Zone) into Result
FROM AMI_zones
WHERE (Hfzip <= LEFT(ZipCode, 5)) AND (Htzip >= LEFT(ZipCode, 5));
if Result is null or Result < 1 or (Result > 11 and Result <> 99) Then
/*if the left most character is alpha, then set the zone to 98 for Canada*/
if Left(zipCode, 1) >= 'A' and LEFT(zipcode,1) <= 'Z' THEN
set result = 98;
else
set Result = 99;
End if;
END if;
RETURN Result;
END;
But this always generates the following error:
SQLSTATE[42000]: Syntax error or access violation: 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 'IN ZipCode varchar()) RETURNS'
So what is the proper way to format a SQL call to be run in a module's install/update script to insert a function or stored procedure into Maganeto's database?
The problem is with your SQL statement:
You have an error in your SQL syntax; check the manual ...
for the right syntax to use near
'IN ZipCode varchar()) RETURNS'
I would recommend running the SQL through PhpMyAdmin or on the command line until you get it right, then run it through Magento. This man page describes the syntax of CREATE FUNCTION: http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html. When testing stored procedures /functions in the mysql client (or PhpMyAdmin) be sure to change the delimiter so that the semicolons in your function body are interpreted correctly.
The below SQL worked for me. The things I changed from your original statement are:
IN is not allowed in function declarations (IN ZipCode varchar())
I was required to explicitly state length of the varchar
The DECLARE belongs inside the function
I am guessing that your function is DETERMINISTIC, meaning it will always produce the same results for the same input parameters. If this is not the case, remove DETERMINISTIC from the RETURNS line
Give this a shot:
DROP FUNCTION IF EXISTS {$this->getTable('fn_Get_HardinessZone')};
CREATE FUNCTION {$this->getTable('fn_Get_HardinessZone')} (ZipCode VARCHAR(15))
RETURNS INTEGER DETERMINISTIC
BEGIN
DECLARE result INTEGER;
SELECT MAX(Zone) INTO result
FROM AMI_zones
WHERE (Hfzip <= LEFT(ZipCode, 5)) AND (Htzip >= LEFT(ZipCode, 5));
IF result IS NULL OR result < 1 OR (result > 11 AND result <> 99) THEN
/* if the left most character is alpha, then set the zone to 98 for Canada */
IF LEFT(ZipCode, 1) >= 'A' AND LEFT(ZipCode, 1) <= 'Z' THEN
SET result = 98;
ELSE
SET result = 99;
END IF;
END IF;
RETURN result;
END;

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.

Stored procedures written in MySQL 5.5.8 don't work in 5.1

I have some stored procedures and a trigger that work great in MySQL 5.5.8 but for some reason don't work in 5.1. The error descriptions aren't enough for me to figure out the problem. Here is the code and the errors.
CREATE PROCEDURE `cg_getMatchingContent`(
MatchTerm VARCHAR(255),
MaxResults INT)
BEGIN
SELECT * FROM (
SELECT t.*, INSTR(t.`Title`,MatchTerm) as Pos
FROM cg_content t ) c
WHERE Pos>0 ORDER BY Pos LIMIT 0, MaxResults;
END
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 'MaxResults' at line 8
DELIMITER ;;
CREATE TRIGGER `cg`.`cg_content_UrlDup_ConstTrig`
BEFORE INSERT ON `cg`.`cg_content`
FOR EACH ROW
Begin
DECLARE errorString VARCHAR(500);
DECLARE insert_error CONDITION FOR SQLSTATE '99001';
IF new.Url = '' THEN
SET errorString = CONCAT('Url cannot be blank
Title: ' , new.Title);
SIGNAL insert_error
SET MESSAGE_TEXT=errorString;
END if;
IF Exists(SELECT id FROM cg.cg_content WHERE Url=new.Url) THEN
SET errorString = CONCAT('Url is not unique
Title: ' , new.Title , '
Url: ' + new.Url);
SIGNAL insert_error
SET MESSAGE_TEXT=errorString;
End if;
End ;;
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 'insert_error
SET MESSAGE_TEXT=errorString;END if;IF ' at line 10
From the docs:
Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables as of MySQL 5.5.6.
5.1 does not support variables in LIMIT and OFFSET.
The second one is easy to figure, hard to fix. SIGNAL and RESIGNAL commands were introduced in MySQL 5.5. You can't convert it easily to 5.1. One way to do it, would be to run a query that errors. For example a SELECT from a non-existent table.