Mysql insert from stored procedure gives error 1064 - mysql

For some strange reason, inserting from stored procedure is not working.
This is what Im trying to do:
DROP TABLE IF EXISTS test;
CREATE TABLE IF NOT EXISTS test(
id INT(9) NOT NULL AUTO_INCREMENT
,name VARCHAR(30) NOT NULL
,PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
insert into test (name) values('A');
Inserting from command line works with no problems.
Then I created a stored procedure to do the same kind of insert:
DROP PROCEDURE IF EXISTS storedtest;
DELIMITER $$
CREATE PROCEDURE storedtest()
BEGIN
declare insert_sql varchar(200);
SET insert_sql = 'insert into test (name) values(3)';
SELECT insert_sql;
PREPARE mystm FROM #insert_sql;
EXECUTE mystm;
END$$
DELIMITER ;
call storedtest();
This gives me the error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
NULL? Where did NULL came from?
I also tried changing the sql-insert to look like this (dont know if it is a good way):
SET insert_sql = "insert into test (name) values('3')";
But mysql gives me exactly the same error.
Anyone has a clue?

The NULL MySQL is reporting is an empty user variable #insert_sql, which is different from the local stored procedure local variable insert_sql which you allocated with DECLARE.
MySQL's DECLARE is used for variables local to a stored program, but according to the documentation, PREPARE stmt FROM ... expects either a string literal or a user variable, which are the type preceded with #.
PREPARE stmt_name FROM preparable_stmt
preparable_stmt is either a string literal or a user variable that contains the text of the SQL statement.
You can allocate the untyped user variable with SET so there is no need for DECLARE. You may wish to set it to NULL when you're finished.
DROP PROCEDURE IF EXISTS storedtest;
DELIMITER $$
CREATE PROCEDURE storedtest()
BEGIN
-- Just SET the user variable
SET #insert_sql = 'insert into test (name) VALUES (3)';
SELECT #insert_sql;
-- Prepare & execute
PREPARE mystm FROM #insert_sql;
EXECUTE mystm;
-- Deallocate the statement and set the var to NULL
DEALLOCATE PREPARE mystm;
SET #insert_sql = NULL;
END$$
DELIMITER ;

Related

Pass ANY string as a in parameter to a stored procedure in mysql (dynamic)

I am experiencing some trouble when I pass date-like strings to a input parameter of a stored procedure.
The table I try to modify has following columns:
create table localdevid.product_a(
INDX int PRIMARY KEY NOT NULL AUTO_INCREMENT,
ProdID int unsigned,
Assigned tinyint,
TesterID varchar(8),
tAss datetime);
Now I try to create a stored procedure:
use localdevid;
drop procedure if exists AssignNewDevID;
DELIMITER $$
use localdevid$$
CREATE PROCEDURE AssignNewDevID(in TableName varchar(255), in TesterName varchar(8), out DevID bigint(20))
BEGIN
#declare rightnow datetime;
set #t1=CONCAT("select SensorID into #localID from localdevid.",TableName," where ISNULL(Assigned) and INDX>1 order by INDX asc limit 1 for update");
prepare statement1 from #t1;
execute statement1;
deallocate prepare statement1;
set DevID=#localID;
set #t2=CONCAT("update localdevid.",TableName," set Assigned=4 where SensorID=",DevID);
prepare statement2 from #t2;
execute statement2;
deallocate prepare statement2;
set #t3=CONCAT("update localdevid.",TableName," set TesterID=",TesterName," where SensorID=",DevID);
prepare statement3 from #t3;
execute statement3;
deallocate prepare statement3;
commit;
END $$
DELIMITER ;
There were several issues, therefore I splitted it into the three statements to see where my problems might come from. I surely will later get it back into one statement back later on.
If I call the function the failure message changes:
call AssignNewDevID("product_a",'tester3',#id);
The script runs to statement2, this is executed successfully.
Statement3 drops Error Code 1054: "Unknown column 'tester3' in Field list.
I cannot understand why the parameter is interpreted as a field name.
It gets even stranger, if I pass a string as TesterName, which can be interpreted as a date or time.
In example, the TesterName are usually MAC-IDs, so the string is i.e. "00:08:01" (I transfer only the last 3 bytes of the MAC).
If I call it like this:
call AssignNewDevID("htpa32x32d",'00:08:01',#id);
I get error code: 1064: You have an error in your SQL syntax; check the manual...
What I am doing wrong here? Why can I concat TableName and DevID but not TesterName?
I don't see any difference here to the the other parameters.
Furthermore, I was not able to pass the current datetime to tAss. I did try the following:
declare rightnow datetime;
declare mydate varchar(20);
select DATE_FORMAT(now(),"%d.%m.%y") as mydate;
...
set #t4=CONCAT("update localdevid.",TableName," set tAss=",mydate," where SensorID=",DevID);
How can I pass basically NOW() to tAss?
OK, got it. Since I pass a string in TesterName I do need of course mark it between 'xxx' in this case.
So it works by
set #t3=CONCAT("update localdevid.",TableName," set TesterID='",TesterName,"' where SensorID=",DevID);
Same applies for the timestamp:
set #mydate=DATE_FORMAT(now(),"%d.%m.%y %h:%i:%S");
set #t4=CONCAT("update localdevid.",TableName," set tAss='",#mydate,"' where SensorID=",DevID);

can't create a table in mysql with dynamic sql

This is my code in MySQL.
USE database;
DROP procedure IF EXISTS CreateTable;
DELIMITER $$
USE ims_data$$
CREATE PROCEDURE CreateTable ()
BEGIN
Set #SqlQuery = Concat('DROP TABLE IF EXISTS mytemptable;');
Set #SqlQuery = Concat(#SqlQuery,'\r\n','create table mytemptable');
Set #SqlQuery = Concat(#SqlQuery,'\r\n','(');
Set #SqlQuery = Concat(#SqlQuery,'\r\n','Column1 int,');
Set #SqlQuery = Concat(#SqlQuery,'\r\n','Column2 varchar(500)');
Set #SqlQuery = Concat(#SqlQuery,'\r\n',');');
Set #SqlQuery = Concat(#SqlQuery,'\r\n','Select * from mytemptable;');
#Select #SqlQuery;
PREPARE Statement From #SqlQuery;
EXECUTE Statement;
DEALLOCATE PREPARE Statement;
END$$
DELIMITER ;
call GetUploadInformation();
I am trying to create a table but it is giving me an 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 'create table mytemptable (Stockist_Code int,Status varchar(500) ); Sele' at line 2
This is the output of query.
DROP TABLE IF EXISTS mytemptable;
create table mytemptable
(
Column1 int,
Column2 varchar(500)
);
Select * from mytemptable;
Which is working fine when executing this code withoug calling the procedure.
PREPARE/EXECUTE can only process one statement at a time. You're trying to execute two with the ;.
The error message gives you a clue in that it ran the two statements together.
You'll have to run them as separate statements.

MySQL: prepared Statement in a stored Procedure - parameter error 1064

I'm creating a sql script for a migration functionality of ours. We want to migrate data from one magento-instance to another (using pure SQL because the import/export of magento is pretty limited).
One of the challenges ist that I want to dynamically alter the AUTO_INCREMENT value of a table so it doesn't need to be done manually in multiple steps. I want to set the AUTO_INCREMENT value to the current-maximum value of the corresponding column + 1.
I prepared the following stored procedure for this:
DELIMITER $$
CREATE PROCEDURE alter_auto_inc_customer()
BEGIN
SELECT #max := MAX(entity_id)+ 1 FROM customer_entity;
PREPARE stmt FROM 'ALTER TABLE customer_entity AUTO_INCREMENT = ?';
EXECUTE stmt USING #max;
END $$
This command runs smoothly. Afterwards the procedure should just be called by a simple statement:
CALL alter_auto_inc_customer();
When I execute the "call"-statement, I get a 1064 Syntax error. It's probably trivial but I can't figure it out for the life of me...
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 '?' at line 1
Does anyone have an idea what the issue is?
I need to get this into one or more stored procedures because I need to be able to run similar statements for multiple tables in the database.
Instead of altering the table structure you can use a trigger to get the max value + 1 before insert data:
DELIMITER $$
DROP TRIGGER IF EXISTS custom_autoincrement_bi$$
CREATE TRIGGER custom_autoincrement_bi BEFORE INSERT ON customer_entity
FOR each ROW
BEGIN
SET NEW.entity_id = select max(entity_id) + 1 from customer_entity;
END$$
DELIMITER ;
But if you want to alter the table from stored procedure
DELIMITER $$
CREATE PROCEDURE alter_auto_inc_customer()
BEGIN
SELECT MAX(entity_id) + 1 into #max FROM customer_entity;
set #sql = concat('ALTER TABLE customer_entity AUTO_INCREMENT = ', #max);
PREPARE stmt FROM #sql;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END $$

MySQL ALTER TABLE with arguments in stored procedure

In a MySQL migration script, I'm trying to drop all the foreign keys of a table without knowing the name of the constraints themselves. I need this because I can only be aware of the constraints names in a particular database installation, but the script has to work also in other installations where the name is unknown at current script coding time.
Here is my first guess of a stored procedure, but it doesn't work. In particular it complains about the '?' in ALTER TABLE.
DELIMITER $$
DROP PROCEDURE IF EXISTS drop_foreign_key_documents $$
CREATE PROCEDURE drop_foreign_key_documents ( )
BEGIN
WHILE (SELECT COUNT(*) AS index_exists FROM `information_schema`.`TABLE_CONSTRAINTS` c WHERE `c`.`CONSTRAINT_TYPE` LIKE '%FOREIGN%' AND `c`.`TABLE_NAME`='documents' and `c`.`TABLE_SCHEMA`='mydb') > 0 DO
SET #ctype = '%FOREIGN%';
SET #tname = 'documents';
SET #dbname = 'mydb';
SET #n = 'select `CONSTRAINT_NAME` INTO #cname FROM `information_schema`.`TABLE_CONSTRAINTS` c WHERE `c`.`CONSTRAINT_TYPE` LIKE ? AND `c`.`TABLE_NAME`=? and `c`.`TABLE_SCHEMA`=? LIMIT 0,1';
PREPARE stmt FROM #n;
EXECUTE stmt USING #ctype,#tname,#dbname;
SELECT #cname;
SET #s = 'ALTER TABLE `documents` DROP FOREIGN KEY ?';
PREPARE stmtd FROM #s;
EXECUTE stmtd USING #cname;
END WHILE;
END $$
DELIMITER ;
CALL drop_foreign_key_documents;
The output of MySQL is:
#cname
documents_ibfk_13
ERROR 1064 (42000) at line 23: 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 1
Now I can imagine why it complains: the ALTER TABLE statement cannot use '?' because the constraint name is not part of a WHERE clause and so it cannot be replaced by a positional parameter. What I don't know is how to build a parametrized ALTER TABLE statement.
Obvious answer:
SET #s = CONCAT('ALTER TABLE `documents` DROP FOREIGN KEY ', #cname);
PREPARE stmtd FROM #s;
EXECUTE stmtd;

EXECUTE in MySQL Stored Procedure gives syntax error

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//