I've created the following stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `ABON_PLATA`(DATE_BAL1 datetime)
BEGIN
DECLARE IMSI1 varchar(6);
DECLARE DATE1 datetime;
DECLARE ID_U1 integer;
DECLARE PAY1 double;
DECLARE PAYSUM double;
DECLARE OLD1 double;
DECLARE REASON1 varchar(16);
DECLARE FLAG integer DEFAULT 0;
DECLARE C1 CURSOR FOR SELECT ID_U FROM podkl_otkl_uslug WHERE IMSI1=IMSI;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET FLAG=1;
OPEN C1;
REPEAT
FETCH C1 INTO ID_U1;
IF FLAG=0 THEN
SELECT SUM(PAY) INTO PAY1 FROM uslugi WHERE ID_U1=ID_U AND DATE_PODKL<DATE_BAL1 AND DATE_OTKL IS NULL;
SET REASON1 = 'ABON PLATA';
SET DATE1 = DATE_BAL1;
SET PAYSUM = `NEW`-PAY1;
SET OLD1 = `NEW`;
END IF;
INSERT history (`DATE`, REASON, `NEW`, OLD, IMSI) VALUES (DATE1, REASON1, PAYSUM, OLD1, IMSI1);
UNTIL FLAG=1
END REPEAT;
CLOSE C1;
END
It is used to simulate subscribtion fee of mobile operator. As I am trying to call it, I get the notorious error:
CALL ABON_PLATA(2013-07-07 12:00:00);
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 '12:00:00)' at line 1
Considering it is an error at line 1, I get extremely confused. What super obvious am I missing?
Datetime literals must be in quotes.
CALL ABON_PLATA('2013-07-07 12:00:00');
The reason it reports an error at line 1 is that it's the CALL line that contains an error. It has nothing to do with your procedure code, because the error happens before it can even call your procedure.
Re your comment:
Thread stack overrun: 6892 bytes used of a 131072 byte stack, and 128000 bytes needed. Use 'mysqld --thread_stack=#' to specify a bigger stack.
This indicates that your MySQL has a configured value of thread_stack that is too small to run statements in Stored Procedures. This can happen, for example, if you use the my-small.cnf configuration file that is bundled with some releases of MySQL.
Increase the value of thread_stack in your configuration file. The default is 256K, and it's only the my-small.cnf that sets it lower. There has been a bug logged about this setting being too low.
Don't forget to restart your MySQL service after you make this change to the config file.
Related
I must find the sum of the first 100 natural numbers. 1+2+3+...+n, and so on. While using "while loops".
delimiter $
create procedure `calcul`.somme()
begin
declare s int default 0;
declare i int default 1;
while(i<=100) do
set s := s+i;
set i := i+1;
end while;
select s;
end;
$
call `calcul`.somme()
when I call the somme() I'm getting this error -->
call calcul.somme()= Error Code: 2013. Lost connection to MySQL server during query
The query is taking too long and the engine is timing out.
You can edit the SQL Editor preferences in MySQL Workbench:
In the application menu, select Edit > Preferences > SQL Editor.
Look for the MySQL Session section and increase the DBMS connection read time out value.
Save the settings, quite MySQL Workbench and reopen the connection.
use calcul;
delimiter $
create procedure somme()
begin
declare s int default(0);
declare i int default(1);
while(i<=100) do
set s := s+i;
set i := i+1;
end while;
select s;
end;
$
CALL somme()
thanks, the Problem solved 👌
I run the following script:
USE MODERN_FAMILY;
DROP FUNCTION IF EXISTS compare_news;
DELIMITER $$
CREATE FUNCTION compare_news(n INT, m INT)
RETURNS VARCHAR(20)
BEGIN
DECLARE s VARCHAR(20);
IF n>m THEN SET s='>';
ELSEIF n=m THEN SET s='=';
ELSE SET s='<';
END IF;
SET s = CONCAT(n, ' ', s, ' ',m);
RETURN s; END;$$
First script returns this error :
Error Code: 1418. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable).
Then, I run this:
USE MODERN_FAMILY;
SELECT compare_news(2,5);
It returns this error:
Error Code: 2014. Commands out of sync; you can't run this command now.
Does someone know if I have an error with the script? Or is related to my SQL configuration?
log_bin_trust_function_creators variable controls whether binary logging should trust the stored function creators for not to create unsafe stored functions.
Reference: Stored Program Logging
When you create a stored function, you must declare either that it is
deterministic or that it does not modify data. Otherwise, it may be
unsafe for data recovery or replication.
By default, for a CREATE FUNCTION statement to be accepted, at least
one of DETERMINISTIC, NO SQL, or READS SQL DATA must be specified
explicitly. Otherwise an error occurs:
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL,
or READS SQL DATA in its declaration and binary logging is enabled
(you *might* want to use the less safe log_bin_trust_function_creators
variable)
To relax the preceding conditions on function creation (that you must
have the SUPER privilege and that a function must be declared
deterministic or to not modify data), set the global
log_bin_trust_function_creators system variable to 1.
Solution 1: Make your function which doesn't manipulate data or deterministic in nature
CREATE FUNCTION `compare_news`(
`n` INT,
`m` INT
) RETURNS VARCHAR(20) CHARSET latin1 LANGUAGE SQL DETERMINISTIC NO SQL SQL SECURITY DEFINER COMMENT ''
BEGIN
DECLARE s VARCHAR(20);
IF n>m THEN
SET s='>';
ELSEIF n=m THEN
SET s='=';
ELSE
SET s='<';
END IF;
SET s = CONCAT(n, ' ', s, ' ',m);
RETURN s;
END
Solution 2: Enable MySQL to trust such functions by setting mysql log_bin_trust_function_creators variable to ON.
Reference: log_bin_trust_function_creators
SET GLOBAL log_bin_trust_function_creators = 1;
The variable will change upon restart if you do not update the config to reflect the change.
I'm converting SQL Server stored procedures to MySQL and running into issues. I have a stored procedure with an IF THEN ELSE that, while not giving errors, is not returning any data either and I'm not seeing the problem to fix it. The queries by themselves are correct and return data but don't seem to work in the stored procedure. This is a simplified version of the real query just FYI.
The SQL for creating the stored procedure is:
DROP PROCEDURE IF EXISTS `sp_GetVolunteerAwardsList`;
DELIMITER //
CREATE PROCEDURE `sp_GetVolunteerList`( IN glAward_in int)
BEGIN
DECLARE glAward_In INT;
DECLARE awardType_In varchar(100);
DECLARE awardActive INT;
IF (glAward_In) = 0 THEN
SELECT * FROM tbl_volunteer
ELSEIF (glAward_In) = 1 THEN
SELECT * FROM tbl_volunteerpositions
END IF;
END
//
As always, any assistance would be most appreciated.
Check the glAward_In parameter or variable.
The SP is receiving the parameter glAward_in, i in lower case.
Then there is a DECLARE that declares a different variable glAward_In, i in upper case.
The if is done using the glAward_In in uppercase which is not set in any place of the SP. And the parameter in lower case is not used anywhere in the SP.
I think you have to remove the DECLARATION of the variable in upper case, and use the parameter in lowercase for the IF evaluation.
I just keep getting the error 1064. I searched how to do while loops then declare local variables etc. and I don't see what I'm doing wrong. I tried to do it without the ";" and I tired setting the delimiter as "|" to be able to use ";" as a separator between lines (I read something somwhere that kind of said it could be the way to do it?..)
I'm trying to do that query on PhpMyAdmin and my MySql version is 5.1.36
I'm not going to explain what I'm trying as I believe it is easy to understand by simply reading my query below.
BEGIN
DECLARE v1 INT DEFAULT 0;
DECLARE v2 VARCHAR(10);
WHILE v1 < 20 DO
SET v2 = CONCAT('Test ', CAST(v1 AS CHAR(2)));
INSERT INTO news(title,date, message) VALUES(v2, NOW(), v2);
SET v1 = v1 + 1;
END WHILE;
END;
MySql only allows compound statements using the BEGIN...END tag inside stored programs.
From the Docs:
BEGIN ... END syntax is used for
writing compound statements, which can
appear within stored programs
The first thing i can see is a small syntax error within the CAST parameters.
You have:
CAST(v1 ASCHAR(2))
You need:
CAST(v1 AS CHAR(2))
See http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html#function_cast
Change
DECLAREv2 VARCHAR(10);
to
DECLARE v2 VARCHAR(10);
Over the last couple of days I have tried to write an Stored procedure in MySQL and I have some truble getting it to work. Hope someone here can give me some input :)
The example I post is for asp.Net Membership provider to create a new user. I expect to send email and password to the DB and get an int return to verify that the userdeatils was written to the DB.
I use a MySQL DB 5.1 (I think) and write the SQL to a webinterface.
I got 2 sidequestions, can someone explain that too :):
1) I use a DELIMITER, but do not know what it does.
2) I am not sure if I have to do other things then to set autocommit = 0 to get transactions to work, or if I even have to do that.
I know that I could have used a IF / ELSE statement instead of a transaction, but would like to do it with one to find out how it works. (I expect to use it alot later)
The code I can not get to work:
DELIMITER //
CREATE DEFINER=`websharp_dk`#`%` PROCEDURE `CreateUser`(
IN _username VARCHAR(100),
IN _Password VARCHAR(100))
RETURNS INT
BEGIN
SET autocommit = 0;
DECLARE return_value INT;
BEGIN TRY
START TRANSACTION
INSERT INTO User
(Email
,Password
,Failed_Password_Count
,Creation_Date)
VALUES
(_username
,_Password
,0
,Datetime.Now())
SET return_value = 1;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK
SET return_value = 0;
END CATCH
BEGIN FINALLY
RETURN return_value;
END FINALLY
END//
DELIMITER ;
Edit:
The error message I get is:
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 'INT BEGIN SET autocommit = 0; DECLARE return_value INT; ' at line 4
To get support for transactions, make sure you are using the InnoDB storage engine rather than the default MyISAM.
As far as that code itself, my first question would be, why are you wrapping that single query in a transaction? Also, what errors are you seeing?
The delimiter redefines what sequence of characters you use to end an sql statement. The entire create procedure is one big statement and you need to tell MySQL where it ends with something (would normally be ';'). But since you have a bunch of other statements in the "body" (between BEGIN and END) of the create procedure statement that all need to be ended too you need to redefine the delimiter so you don't end the create procedure statement at the first ';'.
Without redefining the delimiter, MySQL would think that the create procedure statement looked like this and then begin a new statement:
CREATE DEFINER=`websharp_dk`#`%` PROCEDURE `CreateUser`(
IN _username VARCHAR(100),
IN _Password VARCHAR(100))
RETURNS INT
BEGIN
SET autocommit = 0;
Using DELIMITER ; at the end of the script changes the delimiter back to ';' and is not needed although it's good practice to do so.