I am trying to write a generic sql procedure that can execute any string as a sql statement.
Here is the procedure definition.
DELIMITER //
DROP PROCEDURE IF EXISTS execute_dynamic_sql;
CREATE PROCEDURE execute_dynamic_sql (IN sql_query longtext)
BEGIN
SELECT sql_query;
PREPARE stmt FROM #sql_query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
I am calling the above function like this
mysql> call execute_dynamic_sql('show tables');
-> //
+-------------+
| sql_query |
+-------------+
| show tables |
+-------------+
1 row in set (0.00 sec)
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
mysql> #
Can somebody tell me why is the error coming ?
It is important to indicate the difference between 9.4. User-Defined Variables and routine parameters 13.1.15. CREATE PROCEDURE and CREATE FUNCTION Syntax, are different variables.
In your example #sql_query is NULL and sql_query is assigned to SHOW TABLES.
Try:
DELIMITER//
CREATE PROCEDURE `execute_dynamic_sql` (IN `sql_query` LONGTEXT)
BEGIN
SET #`sql_query` := `sql_query`;
PREPARE `stmt` FROM #`sql_query`;
EXECUTE `stmt`;
DEALLOCATE PREPARE `stmt`;
END//
DELIMITER;
SQL Fiddle demo
Related
Please help me with my query:
I have below mentioned stored procedure in oracle and I need to convert it to MySQL
CREATE OR REPLACE procedure EAMP.EXEC_DDL (SQLSTMT VARCHAR2) AUTHID DEFINER
is
BEGIN
EXECUTE IMMEDIATE SQLSTMT
END EXEC_DDL;
/
This is what I have created in MySQL (version 5.7):
DROP PROCEDURE IF EXISTS EXEC_DDL;
CREATE DEFINER=`ampd_own`#`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set #sql = SQLSTMT;
PREPARE STMT FROM #sql;
EXECUTE STMT;
deallocate prepare STMT;
END;
but it is giving me below mentioned error:
20:08:43 START Executing, Database Connection: EAMP DEV MYSQL Database Type: MYSQL Catalog: ampd01 Schema: null
20:08:47 INFO Physical database connection acquired for: EAMP DEV MYSQL
20:08:47 WARNING [DROP - 0 rows, 0.994 secs] OK. No rows were affected
SQLWarning:
Code: 1305 SQL State: 42000 --- PROCEDURE ampd01.EXEC_DDL does not exist
DROP PROCEDURE IF EXISTS EXEC_DDL;
20:08:48 FAILED [CREATE - 0 rows, 1.245 secs] [Code: 1064, SQL State:
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 4
CREATE DEFINER=`ampd_own`#`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set #sql = SQLSTMT;
20:08:49 FAILED [PREPARE - 0 rows, 1.243 secs] [Code: 1064, SQL State:
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
PREPARE STMT FROM #sql;
20:08:51 FAILED [EXECUTE - 0 rows, 1.253 secs] [Code: 1243, SQL State:
HY000] Unknown prepared statement handler (STMT) given to EXECUTE
EXECUTE STMT;
20:08:52 FAILED [DEALLOCATE - 0 rows, 1.255 secs] [Code: 1243, SQL State:
HY000] Unknown prepared statement handler (STMT) given to DEALLOCATE
PREPARE
deallocate prepare STMT;
20:08:53 FAILED [END - 0 rows, 1.253 secs] [Code: 1064, SQL State: 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 'END' at line 1
END;
20:08:55 END Execution 6 statement(s) executed, 0 row(s) affected,
exec/fetch time: 7.243/0.000 secs [1 successful, 1 Warnings, 5 errors]*/
With semicolons in the body of the procedure, we need to change the statement delimiter for the session.
For example:
DELIMITER $$
CREATE PROCEDURE foo()
BEGIN
SELECT NOW();
END$$
DELIMITER ;
With that, the semicolon that appears in the stored procedure does not end the CREATE statement. And we can change the statement delimiter back to semicolon when we're done.
EDIT
Here's an analysis of the reported output:
This statement
DROP PROCEDURE IF EXISTS EXEC_DDL;
completed successfully, raising a warning "procedure does not exist"
The next statement executed was this:
CREATE DEFINER=`ampd_own`#`%`
PROCEDURE `ampd01`.`EXEC_DDL`(in SQLSTMT VARCHAR(4000))
BEGIN
set #sql = SQLSTMT;
MySQL returned a syntax error; which is expected behavior, because that's not a valid SQL statement. The next statement executed:
PREPARE STMT FROM #sql;
returned an error, because #sql evaluates to NULL. The next statement executed
EXECUTE STMT;
failed because STMT isn't a valid statement handle. (Because the PREPARE failed.)
We don't want to execute the SET and PREPARE as separate statements, we want those to be part of the CREATE PROCEDURE statement.
The problem is that the semicolon character is the statement terminator; we need to change the statement terminator to be something else, to some string that doesn't appear in the body of the CREATE PROCEDURE.
FOLLOWUP
Reference: https://dev.mysql.com/doc/refman/5.7/en/stored-programs-defining.html
Here's a demonstration using the MySQL Command Line Client
# mysql --defaults-extra-file=/opt/mysql/scripts/config.cnf --database test
mysql> DELIMITER $$
mysql> DROP PROCEDURE IF EXISTS foo $$
Query OK, 0 rows affected (0.06 sec)
mysql> DROP PROCEDURE IF EXISTS foo $$
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE PROCEDURE foo()
-> BEGIN
-> SELECT NOW();
-> END$$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> CALL foo();
+---------------------+
| NOW() |
+---------------------+
| 2018-06-13 13:33:33 |
+---------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> exit
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 have the following stored procedure:
CREATE PROCEDURE getLastValueAutomaticShelter(IN fieldName varchar(30), position_number INT)
BEGIN
SET #query = CONCAT('SELECT * FROM automatic_changes WHERE',fieldName,'IS NOT NULL AND P_id=?');
PREPARE stmt FROM #query;
SET #position_number=position_number;
EXECUTE stmt USING #position_number;
DEALLOCATE PREPARE stmt;
END
Then I am running it:
mysql> call getLastValueAutomaticShelter('current_level', 500)//
And getting 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 'NOT N
ULL AND P_id=?' at line 1
Any ideas? Thanks.
You need to add some spaces in there:
SET #query = CONCAT('SELECT * FROM automatic_changes WHERE ',fieldName,' IS NOT NULL AND P_id=?');
/* right ^ here....and ^ here*/
Otherwise your final query might look like this:
SELECT * FROM automatic_changes WHEREcolumnameIS NOT NULL AND P_id='whatever';
You get the idea :)
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 //
I'm trying to set up a stored proc that (in part) drops a user. I've tried several versions of DROP USER that "expand" the argument and I can't find one that works. Can someone help?
DELIMITER //
CREATE PROCEDURE `dropuser`( IN inUser varchar(255) )
BEGIN
#DROP USER concat(inUser,"#localhost");
#DROP USER inUser "#localhost";
#DROP USER "inUser#localhost";
END//
DELIMITER ;
CALL dropuser("asdf");
All three of them fail in the same way:
ERROR 1064 (42000) at line 4: 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 '(inUser,"#localhost");
Obviously I'm getting the expansion wrong.
delimiter //
drop procedure if exists dropuser //
create procedure dropuser( in inUser varchar(255) )
begin
set #str = concat('drop user ', "'",inUser,"'#","'localhost'");
prepare stmt from #str;
-- select #str;
execute stmt;
deallocate prepare stmt;
end//
delimiter ;
call dropuser('pippo');