I'm wrestling with MySQL stored procedures, and the PREPARE / EXECUTE statement pair. I'm attempting to run the (simplified) code below in order to create a stored procedure that will encapsulate several queries into a transaction with rollback. I continue to get
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 'goodID;
If I remove the transaction and handlers all is well with the code. If I remove the EXECUTEstatement the procedure can be created.
What am I missing here?
DELIMITER $$
USE `casc`$$
DROP PROCEDURE IF EXISTS `sp_T_MergeMemberIDs`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_T_MergeMemberIDs`(IN goodID VARCHAR(8), OUT param_sp_success TINYINT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
START TRANSACTION;
SET param_sp_success = 0;
SET #SQL=
"SELECT * FROM member
WHERE memberID = ?";
PREPARE stmt FROM #SQL;
EXECUTE stmt USING goodID;
-- queries executed here using the same parameter
-- omitted for simplicity
SET param_sp_success = 1;
COMMIT;
END$$
As far as I remember, you need to use session user variable in execute ...using :
...
PREPARE stmt FROM #SQL;
SET #tmp_var = goodID;
EXECUTE stmt USING #tmp_var;
...
Related
I have two tables,
execution:
execution_id | order_id | execution_date
1 1 2014-03-16
2 1 2014-03-17
and queries:
query_name | code
CNT_EXEC | SELECT COUNT(execution_id) FROM `execution`
We have query defined in a column above. I am trying to execute this query using my code below;
DELIMITER //
DROP PROCEDURE IF EXISTS query_execute //
CREATE PROCEDURE query_execute()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE s_query varchar(255);
DECLARE c_queries CURSOR FOR
SELECT code FROM queries;/*since there are more than one queries in the actual query table*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN c_queries;
getquery: LOOP
FETCH c_queries INTO s_query;
IF finished = 1 THEN
LEAVE getquery;
END IF;
/*run the query*/
SET #sql = s_query;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
END //
DELIMITER ;
/*next I am trying to invoke the procedure and find the results*/
CREATE PROCEDURE queriesExecution()
BEGIN
SELECT query_name, query_execute() AS val
FROM queries;
END
Going by the MySQL documentation, it seems I am using the correct procedure to create the procedure.But here is the error I am getting;
ERROR 1064 (42000) in the pre-written template: 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`.
As i already wrote in my comment, your approach doesn't work .
But you can change it a bit
First:
Change your queries, because you need a result
CREATE TABLE queries (
`query_name` VARCHAR(8),
`code` VARCHAR(355)
);
INSERT INTO queries
(`query_name`, `code`)
VALUES
('CNT_EXEC', 'SELECT COUNT(execution_id) INTO #result FROM `execution`');
As you can see the result is put into a user defined variable. so that ot can be used in the INSERT INT myresult
DELIMITER //
DROP PROCEDURE IF EXISTS query_execute //
CREATE PROCEDURE query_execute()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE s_query varchar(255);
DECLARE c_queries CURSOR FOR
SELECT code FROM queries;/*since there are more than one queries in the actual query table*/
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
CREATE TEMPORARY TABLe myresults(`query` varchar(255), result INT);
OPEN c_queries;
getquery: LOOP
FETCH c_queries INTO s_query;
IF finished = 1 THEN
LEAVE getquery;
END IF;
/*run the query*/
SET #sql = s_query;
PREPARE stmt FROM #sql;
EXECUTE stmt;
INSERT INTO myresults VALUES (s_query,#result);
DEALLOCATE PREPARE stmt;
END LOOP;
SELECT * FROM myresults;
DROP TEMPORARY TABLE myresults;
END //
DELIMITER ;
when you now call CALL query_execute();
you get
query result
SELECT COUNT(execution_id) INTO #result FROM `execution` 2
Of course as you add queries, you will get more rows.
this now assumes you get only INTEGER back in your queries, if not you must change the datatype.
This also only works, because your query returns only 1 result, if get more rows you can't use the user defined variables and you have to look for another approach.
I have the following stored procedure. The idea is to get a list of databases and execute an sql statement.
DELIMITER $$
CREATE PROCEDURE updateMySQL (
IN theSQL varchar(4000)
)
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE theDatabases varchar(100) DEFAULT "";
-- declare cursor for employee email
DEClARE curDatabase
CURSOR FOR
SELECT schema_name FROM information_schema.schemata where SCHEMA_NAME = 'mydb' order by 1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
OPEN curDatabase;
getDatabase: LOOP
FETCH curDatabase INTO theDatabases;
IF finished = 1 THEN
LEAVE getDatabase;
END IF;
-- build email list
-- SET emailList = CONCAT(theDatabases,";",emailList);
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
END LOOP getDatabase;
CLOSE curDatabase;
END$$
DELIMITER ;
I am attempting to execute the stored procedure like this,
SET #theSQL = 'ALTER VIEW `Reports` AS
SELECT DISTINCT
`tableA`.`Id` AS `Id`,
`tableA`.`letterId` AS `letterId`
FROM
`mytable` `tableA`
ORDER BY 1';
call updateMySQL(#theSQL);
EDIT There was an error on executing the procedure,
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 'NULL' at line 1
I am using mysql 8.0.17
Investigate carefully MySQL 8.0 Reference Manual / SQL Statements / Prepared Statements, the section "SQL Syntax Allowed in Prepared Statements".
This section claims FULL list of statements which are allowed in Prepared statements. ALTER VIEW is NOT listed. So it is NOT allowed.
Use DROP VIEW and CREATE VIEW instead.
Always receive and investigate all error messages.
You should change this part
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
to this:
SET #sql:=CONCAT('USE ',#curDatabase);
PREPARE dynamic_statement FROM #SQL;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement; /* don't forget to deallocate */
/* there's a difference between the variables #theSQL and theSQL (your parameter) */
/* IIRC prepare statements need user defined variables or a syntax error occurs. Therefore I simply assign the parameter to a user-defined variable */
SET #theSQL = theSQL;
PREPARE dynamic_statement FROM #theSQL;
EXECUTE dynamic_statement;
DEALLOCATE PREPARE dynamic_statement;
Read more about user-defined variables here: https://dev.mysql.com/doc/refman/8.0/en/user-variables.html
Here the differences are explained: https://stackoverflow.com/a/1010042/447489
When you don't initialize them, their content is just NULL. Since there's a difference between user-defined variables and local variables (and also your parameter variable), your current solution did nothing.
I am creating a stored procedure which will be executing a prepared statement but on the creation the procedure I get mysql syntax error :
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 'PREPARE udpatestatut FROM #req; EXECUTE
updatestatut; DEALLOCATE PREPARE upd' at line 4
I don't see what my mistake is so I need help to understand what I am doing wrong or writting wrong. Here down is the instructions I am executing.
CREATE PROCEDURE changestatut(IN pstatut VARCHAR(10), IN pidpost VARCHAR(255))
COMMENT 'This procedure change the statut of activities.' NOT DETERMINISTIC NO SQL SQL SECURITY DEFINER
SET #req := concat('UPDATE compte set statut=\'', pstatut ,'\' where idpost in (', pidpost ,')');
PREPARE udpatestatut FROM #req; EXECUTE updatestatut; DEALLOCATE PREPARE updatestatut;
idpost parameter is a comma separated value ...e.g: 1,2,3,6
If you have multiple statements in your procedure you need to wrap them in a begin..end you might also be not setting delimiters. Try this
DROP PROCEDURE IF EXISTS changestatut;
DELIMITER $$
CREATE PROCEDURE changestatut(IN pstatut VARCHAR(10), IN pidpost VARCHAR(255))
COMMENT 'This procedure change the statut of activities.' NOT DETERMINISTIC NO SQL SQL SECURITY DEFINER
BEGIN
SET #req := concat('UPDATE compte set statut=\'', pstatut ,'\' where idpost in (', pidpost ,')');
PREPARE udpatestatut FROM #req; EXECUTE updatestatut;
DEALLOCATE PREPARE updatestatut;
END $$
DELIMITER ;
I'm new to MySQL and databases in general. I'm trying to create a MySQL stored procedure but keep getting a vague syntax 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 'sps; EXECUTE stmt USING nn,ee,ll,cc,uu; COMMIT END' at line 11"
If I remove the line "PREPARE stmt ..." then the stored procedure is created. When I put the line back in, I get the error again.
What is it that I am doing wrong?
DELIMITER //
CREATE PROCEDURE `account_create` (nn VARCHAR(25),
ee BIGINT,
ll BIGINT,
cc VARCHAR(100),
uu VARCHAR(25))
BEGIN
DECLARE newId BIGINT;
DECLARE sps VARCHAR(50);
START TRANSACTION;
set sps = 'INSERT INTO account SET name=?, entity=?, ledger=?, tblname=tmpXXX, creation_date=CURDATE(), comment=?, uname=?';
PREPARE stmt FROM sps;
COMMIT;
END//
You must use a User Defined Variable to execute a prepared statement. Rewrite as:
...
BEGIN
DECLARE newId BIGINT;
START TRANSACTION;
set #sps = 'INSERT INTO account SET name=?, entity=?, ledger=?, tblname=tmpXXX, creation_date=CURDATE(), comment=?, uname=?';
PREPARE stmt FROM #sps;
COMMIT;
END//
When creating the following procedure I receive this error message:
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
'd_query;
set d_result = execute stmt;
deallocate prepare stmt; ' at line 15
But after checking I can't see the error. Line 15 relates to 'if d_query is not null then'.
Is this the true error? Or is it not happy to accept an execute as an assignment to d_result?
Any help would be greatly appreciated.
delimiter |
create procedure runtests()
begin
declare d_test_id char(20);
declare d_query text;
declare d_result text;
declare cur cursor for select test_id, query, result from datavalidator order by test_id;
open cur;
repeat
fetch cur into d_test_id, d_query, d_result;
if d_query is not null then
prepare stmt from d_query;
set d_result = execute stmt;
deallocate prepare stmt;
update datavalidator set result = d_result;
end if;
until done end repeat;
close cur;
end;
|
delimiter ; |
"Note that a literal string expression or a user variable are the only ways you can specify the statement to be prepared.", from this documentation.
Try writing the value into a user variable before trying to prepare, perhaps something like:
set #q_sql = d_query;
...or write directly into the user variable in the fetch line.