I have a stored procedure that works, but when I pass a value with a hyphen in it, it errors.
I call my procedure with a value like call create('server-v01',555); and I get 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 '-v01' at line 1
My procedure is as follows:
DELIMITER $$
CREATE PROCEDURE ct(tname varchar(20), sessionsnum INT(11))
BEGIN
DECLARE maxnum INT;
SET #s = CONCAT('INSERT INTO sessions_poll (server_name,sessions_num) VALUES(''',tname,''',',sessionsnum,')');
PREPARE stm FROM #s;
EXECUTE stm;
SET #s = CONCAT('DROP TABLE IF EXISTS ', tname);
PREPARE stm FROM #s;
EXECUTE stm;
SET #s = CONCAT('CREATE TABLE ', tname, ' (num INT, max INT)');
PREPARE stm FROM #s;
EXECUTE stm;
SELECT #maxnum:=max(sessions_num) INTO maxnum FROM sessions_poll WHERE server_name=tname AND DATE(ts)=CURDATE();
SET #s = CONCAT('INSERT INTO ', tname, ' (num,max) VALUES (', sessionsnum,',',maxnum,')');
PREPARE stm FROM #s;
EXECUTE stm;
END $$
DELIMITER ;
My question is, how can I handle a variable with a hyphen in it?
Your question is not how to handle variable with a dash, but how to handle a table with a dash. Your procedure tries to create a table with a name specified in tname. To create (or drop) a table like this you need to quote it with backticks.
DROP TABLE IF EXISTS `server-01`;
In particular you need to
SET #s = CONCAT('DROP TABLE IF EXISTS `', tname, '`');
and the same for other instances.
Whether this is what you really want to do is a question, though ;-)
Related
I have written a MySQL stored procedure that will add a new partition to an existing table:
DELIMITER //
DROP PROCEDURE IF EXISTS cr_par //
CREATE PROCEDURE cr_par (
IN p_table VARCHAR(256),
IN p_date DATE
) BEGIN
DECLARE stmt VARCHAR(1024);
DECLARE ddl VARCHAR(512);
DECLARE par_name VARCHAR(20) DEFAULT '';
DECLARE par_no INT DEFAULT 0;
DECLARE lt_value INT DEFAULT 0;
SET par_no = TO_DAYS(p_date) + 1;
SET par_name = CONCAT('p', par_no);
SET lt_value = par_no + 1;
SET ddl = CONCAT('ALTER TABLE ', p_table, ' ADD PARTITION (PARTITION ', par_name, ' VALUES LESS THAN (', lt_value, '))');
PREPARE stmt FROM #ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT ddl;
END //
DELIMITER ;
When I run the stored procedure I get this error:
mysql> CALL cr_par('test', '2021-09-13');
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 'NULL' at line 1
If I comment out the PREPARE, EXECUTE and DEALLOCATE statements and re-run the stored procedure I get this, which is a valid DDL statement:
mysql> CALL cr_par('test', '2021-09-13');
+------------------------------------------------------------------------------+
| ddl |
+------------------------------------------------------------------------------+
| ALTER TABLE test ADD PARTITION (PARTITION p738412 VALUES LESS THAN (738413)) |
+------------------------------------------------------------------------------+
1 row in set (0.01 sec)
I've also tried these variations and all return the same error:
SET ddl = 'ALTER TABLE test ADD PARTITION (PARTITION p738412 VALUES LESS THAN (738413));';
PREPARE stmt FROM #ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
and this...
SET ddl = CONCAT('ALTER TABLE ? ADD PARTITION (PARTITION ? VALUES LESS THAN (?))');
PREPARE stmt FROM #ddl;
EXECUTE stmt USING #p_table, #par_no, #lt_value;
DEALLOCATE PREPARE stmt;
I am using this version of MySQL:
Server version: 8.0.25-15 Percona Server (GPL), Release 15, Revision a558ec2
Does anyone have any ideas what could be causing this, I must be missing something simple?
SET ddl = CONCAT('ALTER TABLE ', p_table, ' ADD PARTITION (PARTITION ', par_name, ' VALUES LESS THAN (', lt_value, '))');
PREPARE stmt FROM #ddl;
Please be aware that ddl and #ddl are two different variables.
The variables you declare with the local variable DECLARE statement have a scope within the body of one stored routine. They are never spelled with a # sigil.
The user-defined variables with the # sigil have a scope of a MySQL session. You don't need to declare these kinds of variables. Just setting the variable to a value implicitly creates the variable.
You cannot SET ddl = ... and expect that string to be read from the #ddl variable. Nor vice-versa.
The PREPARE statement only supports preparing an SQL from a user-defined variable. Which means you must set the #ddl variable to your SQL statement:
SET #ddl = CONCAT('ALTER TABLE ', p_table, ' ADD PARTITION (PARTITION ', par_name, ' VALUES LESS THAN (', lt_value, '))');
Then you don't need to DECLARE ddl at all, since there's no use for that variable.
I am trying to executing a mysql query like this
SET #id := '47';
SET #table := #id+'_2013_2014_voucher';
SELECT * FROM #table;
Delete FROM #table where id=#id
It showing error like this
[Err] 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 '#table' at line 1
How I can achieve that?
The usage of dynamic table names within the query is best with Prepared Staments,
also in mysql for concatenation the function is concat
SET #id := '47';
SET #table := concat(#id,'_2013_2014_voucher');
set #qry1:= concat('select * from ',#table);
prepare stmt from #qry1 ;
execute stmt ;
You can do it for the delete query as well
You need to use prepared statements for dynamic table name. Prepared statements support parameters, but you can't use them for table names.
Also to put strings together you have to use CONCAT().
Oh, and you have to do all this in a stored procedure.
Create one like this:
DELIMITER $$
CREATE PROCEDURE sp_exec_dynStmt()
BEGIN
SET #id := 47; /*The single-quotes made it a string, that's not necessary*/
SET #table := CONCAT(#id, '_2013_2014_voucher');
SET #sql := CONCAT('SELECT * FROM ', #table, ';');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = CONCAT('DELETE FROM ', #table, ' WHERE id = ?;'); /*The id can be a parameter, but not the table name*/
PREPARE stmt FROM #sql;
EXECUTE stmt USING #id;
END $$
DELIMITER ;
Then execute it like this:
CALL sp_exec_dynStmt();
try changing that line with
SET #table = '`' + #id+'_2013_2014_voucher`';
usually I declare variable in this way
SET #id = '47'; (without :)
you should use only : with SET, := to assigning variable in a SELECT
I have created the following MySQL SP successfully..
CREATE DEFINER=`root`#`%` PROCEDURE `Common_Proc_Create_NewId`
(
TableName VARCHAR(250),
ColumnName VARCHAR(150),
OUT ReturnId BIGINT
)
BEGIN
DECLARE varb BIGINT;
SET #NewId:= CONCAT('SELECT (IFNULL(MAX(', ColumnName, '), 0) + 1) INTO ', varb, ' FROM ', TableName);
PREPARE Stmnt FROM #NewId;
EXECUTE Stmnt;
DEALLOCATE PREPARE Stmnt;
SET ReturnId = varb;
END$$
But when this was called from another SP I got the following error:
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
Calling SP
CREATE DEFINER=`root`#`%` PROCEDURE `Masters_Proc_Create_BranchType`(
BranchTypName VARCHAR(100)
)
BEGIN
CALL Common_Proc_Create_NewId('Masters_BranchType', 'BranchTypeId', #Id);
INSERT INTO Masters_BranchType (BranchTypeId, BranchTypeName) VALUES (#Id, BranchTypName);
SELECT #Id;
END$$
In your stored procedure Common_Proc_Create_NewId the part into varb was causing the issue and think it's not allowed that way in a prepared statement (not sure though). Instead the way you are doing, try like below and it works fine (a sample code included)
delimiter //
CREATE PROCEDURE dynamic1(IN tbl VARCHAR(64), IN col VARCHAR(64), OUT ret int)
BEGIN
SET #s = CONCAT('SELECT #i := (IFNULL(MAX(', col, '), 0) + 1) FROM ', tbl);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set ret = #i;
END
//
delimiter ;
call dynamic1('test1','col',#id);
select #id;
I am trying to create a procedure to change a string in an entire database... after a lot of searching I have come up with this procedure, but it gives an error. The procedure is:
BEGIN
declare t,c varchar(100);
declare TABLES cursor for SELECT table_name, column_name
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='MY_DATABSE';
declare exit handler for 1329 begin end;
open tables;
looping: loop
fetch tables into t,c;
SET #s1= CONCAT('UPDATE ',
'MY_DATABASE', '.', t, ' SET ',
c, ' = replace(', c,', \'', old, '\'', ' , ', '\'', new, '\')');
PREPARE stmt FROM #s1;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end loop;
close tables;
END
And the error when calling the procedure with any parameter is the well known 1064 error in syntax: check the manual that corresponds to your MySQL server version for the right syntax to use near 'column_to_update(c) = replace(column_to_update(c), 'old' , 'new')' at line 1
What I want to do is,create a table in mysql by passing the table name as a parameter in the stored procedure.I'm using following code for stored procedure in mysql.
DELIMITER //
CREATE PROCEDURE createtable(IN tablename varchar(20))
BEGIN
SET #s=CONCAT('CREATE TABLE', tablename, '(month varchar(20))');
PREPARE stmt FROM #s;
EXECUTE stmt;
END //
and when i call it
CALL createtable('account');
I get the following error
You have an error in your SQL syntax; check the MySQL server version for the right syntax to us...
I don't know where I'm wrong..
You forgot the spaces before and after your table name. Try
DELIMITER //
CREATE PROCEDURE createtable(IN tablename varchar(20))
BEGIN
SET #s=CONCAT('CREATE TABLE ', tablename, ' (month varchar(20))');
PREPARE stmt FROM #s;
EXECUTE stmt;
END //