Using procedure variables to create server-side prepared statements — MySQL - mysql

Within procedures, why does using session-specific variables to store string queries work:
DELIMITER $$
CREATE PROCEDURE `test_prepared_stmt` () BEGIN
SET #q:="SELECT * FROM t1";
PREPARE query FROM #q;
#...
END$$
but using procedure variables not:
DELIMITER $$
CREATE PROCEDURE `test_prepared_stmt` () BEGIN
DECLARE q TEXT;
SET q:="SELECT * FROM t1";
PREPARE query FROM q;
#...
END$$
and instead throw the following 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 'q;
END' at line 5
Is this just a quirk of the language?

You need to use SQL standard variable syntax - all variables are declared/used with the # symbol.
So, in your example, if you used:
declare #q text
or,
declare #q nvarchar(4000)
or anything similar, it will work - just follow the SQL spec for usage of variables and you should be fine, regardless of whether you are within a procedure or passing a parameter, or anything else.

Related

SQL 1064 in Procedures

Hey I'm leraning right now for my study Exams.
I have a Problem with Procedures and Functions.
CREATE PROCEDURE testProc()
BEGIN
DECLARE testNR INT;
END
This is my testCode but every Procedure and every Function gives me this Failure:
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 '' at line 3
SQLState: 42000
ErrorCode: 1064
Error occurred in:
CREATE PROCEDURE testProc()
BEGIN
DECLARE testNR INT
Is there something that I do wrong or do I have Problems with my IDE SQuirrel?
You need to change delimiters while creating the procedure; otherwise ; is seen as the end of the CREATE PROCEDURE statement.
As explained in the docs, you need to
use[] the mysql client delimiter command to change the statement delimiter from ; to // while the procedure is being defined. This enables the ; delimiter used in the procedure body to be passed through to the server rather than being interpreted by mysql itself. See Section 23.1, “Defining Stored Programs”.
It doesn’t have to be //; another common choice is $$.
In your example, this might look like
DELIMITER $$
CREATE PROCEDURE testProc()
BEGIN
DECLARE testNR INT;
END
$$
DELIMITER ;

Syntax error in mysql new version

I have a problem with this, and I keep getting this error
MySQL said: Documentation
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 5.
Do you have any ideas for why I keep getting this error?
DROP PROCEDURE IF EXISTS `prn_insert`;
CREATE PROCEDURE `prn_insert`(id int, name text, description text)
BEGIN
insert into test
select id,name,description;
END
The semicolon is ending the CREATE PROCEDURE statement. To get the entire statement, use a delimiter other than a semicolon. We frequently use $$ (two dollar signs) as a delimiter, but you can use any character sequence that doesn't appear within the statement(s) you want to execute.
For example:
DELIMITER $$
DROP PROCEDURE myproc $$
CREATE PROCEDURE myproc(arg INT)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = 1;
END$$
DELIMITER ;
Once the new delimiter is set, it stays in effect until it's changed to something else. So. we usually want to set it back to semicolon immediately after the `CREATE PROCEDURE' statement.

IF-ELSE Not Working While Calling a Procedure

I am trying to call a procedure with a MySQL command as an argument. Everything is working perfect, but last procedure call where there has been implemented a conditional statement is behaving badly. The error description encountered when the procedure is called is provided below:
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 'IF #CheckExists > 0 THEN
set #result= ('done')
For more information, here i am passing a statement that should have been implemented itself in a procedure (i guess, loops, cursors conditions has to be defined in a procedure in MySQL) and hence an error. But i could not figure this out as the database name (#dbname in this case) has to be passed dynamically and even i tried to make another procedure to make this work i end up with the same error.
Any help would be greatly appreciated.
Thanks
use test;
drop procedure if exists test;
set #dbname = 'test_qa';-- only for the sake of example. this is to be dynamically done
delimiter //
create procedure test(IN sqlCommand text)
begin
SET #tquery = sqlCommand;
PREPARE stmt FROM #tquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end//
delimiter ;
CALL test (concat('SET #CheckExists =(select COUNT(*) from ',#dbname,'.course
where Name = ''Computing'' and Value = ''True'')'));
-- call test ('select #CheckExists');
CALL test (concat('IF #CheckExists > 0 THEN
set #result = (''done'')
else
set #result = (''gone'')
end if'));
You can't use IF (or procedural code at all) in anonymous blocks in MySQL.
Use this:
CALL test('SET #result = CASE WHEN #checkExists > 0 THEN ''done'' ELSE ''gone'' END')

EXISTS and output parameter in stored procedure in mysql

Here is my stored procedure for returning true if any data is found in document details but it generates an 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 '#result = true end if end' at line 5"
create procedure abcde(out result boolean)
begin
if exists(select * from document_details)
then #result = true;
end if
end
Kindly,provide me a solution asap
Besides the fact that you need to use SET to assign a value to a local variable or a parameter, there are other things worth mentioning
you have to have a semicolon after END IF
since EXSITS() returns BOOLEAN you can just directly assign it to your OUT parameter
That being said your stored procedure might look like
CREATE PROCEDURE abcde(OUT result BOOLEAN)
SET result =
(
EXISTS(SELECT *
FROM document_details)
);
Note: now it's just one statement. Therefore you don't even need to change DELIMITER and use BEGIN ... END block.
Here is SQLFiddle demo

In mysql dynamic stored proc, is #var required to build a prepared statement?

I have a similar stored proc (but longer). It is called from PHP (GET request on Apache)
delimiter //
CREATE PROCEDURE dynamic(IN tbl CHAR(64), IN col CHAR(64))
BEGIN
SET #full_statement = CONCAT('SELECT ',col,' FROM ',tbl );
PREPARE stmt FROM #full_statement;
EXECUTE stmt;
END
//
delimiter ;
From what I read, #s is a mysql session variable living as long as my session is alive.
The #s presence annoys me since I fear that 2 concurrent request on that stored
proc might play with this "global variable". So I tried to remove the '#' like this
delimiter //
CREATE PROCEDURE dynamic(IN tbl CHAR(64), IN col CHAR(64))
BEGIN
DECLARE full_statement VARCHAR(300);
SET full_statement = CONCAT('SELECT ',col,' FROM ',tbl );
PREPARE stmt FROM full_statement;
EXECUTE stmt;
END
//
delimiter ;
to build the prepared statement without success.
I seem to have constantly
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 'full_statement; EXECUTE stmt;
Does my fear of 2 calls within my php session is really a problem ?
(If not, what about having 200 stored procedures using that same
global variable) ?
Can I really achieve my goal and remove the '#' and let the prepared
statement being handle by a simple stored proc variable or is it a constraint of prepared statement ?
Regards.
Yes, the #var is required.
MySQL's PREPARE statement only accepts "user variables" (those prefixed with #), not local variables declared in a stored routine.
This has long been recognized as a WTF in MySQL:
Bug #17409 PREPARE doesn't support queries in local variables
Does my fear of 2 calls within my php session is really a problem ?
No. It's not a global variable, it's a session variable.
Two concurrent sessions have their own value for #var.