I have a issue when I try to create a procedure.
First with :
DROP TABLE IF EXISTS curr_rate;
There no problem the table is dropped.
Now with a procedure :
CREATE DEFINER=`root`#`localhost` PROCEDURE `Drop_table_Gen`(IN tname varchar(20))
BEGIN
SET #query = CONCAT('DROP TABLE IF EXISTS `',tname,'`');
PREPARE stm FROM #query;
EXECUTE stm;
END
I get the following error:
error code 1054 Unknown column
The same issue if I write :
CREATE DEFINER=`root`#`localhost` PROCEDURE `drop_table_gen2`(IN tname varchar(20))
BEGIN
DROP TABLE IF EXISTS tname;
END
I hope someone has an idea about this problem
Thanks
First of all, you are calling like call Drop_table_Gen(curr_rate);. shouldn't you be quoting the parameter like call Drop_table_Gen('curr_rate'); since it's a VARCHAR type.
If still same error then I don't see anything wrong with the way you are trying to drop the table. To my believe, somehow IF EXIST is creating the problem here. Try without that (below procedure) and it will work.
CREATE PROCEDURE `Drop_table_Gen`(IN tname varchar(20))
BEGIN
SET #query = CONCAT('DROP TABLE `',tname,'`');
PREPARE stm FROM #query;
EXECUTE stm;
END
If you are using MySQL 5.5 or above then you can use EXIT HANDLER for error catching within your procedure like below
CREATE PROCEDURE `Drop_table_Gen`(IN tname varchar(20))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET #error_count = #error_count + 1;
IF #a = 0 THEN RESIGNAL; END IF;
END;
BEGIN
SET #query = CONCAT('DROP TABLE `',tname,'`');
PREPARE stm FROM #query;
EXECUTE stm;
END
Then while calling the procedure
SET #error_count = 0;
SET #a = 0;
CALL Drop_table_Gen('curr_rate');
So in case, table doesn't exist it will pop up the SQL error
ERROR 1051 (42S02): Unknown table 'curr_rate'
See a detailed document here RESIGNAL Syntax
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 am trying to get data from a table using dynamic procedure with MySQL query.
Is there any way to do it specifically?
I am trying with this procedure below however the variable is still returning as a column.
See code below:
DELIMITER $
DROP PROCEDURE IF EXISTS REC_DATA$
CREATE PROCEDURE REC_DATA( IN_TABLE_NAME VARCHAR(20) )
BEGIN
BEGIN
SET #in_table = IN_TABLE_NAME;
SET #sql_stmt = CONCAT(' SELECT student_id FROM ' , #in_table);
SELECT #sql_stmt;
PREPARE stmt FROM #sql_stmt;
EXECUTE stmt;
END;
END$
DELIMITER ;
I am receiving this error: ERROR: ERROR 1054 (42S22): Unknown column 'SCORE' in 'field list'
Someone can help me?
Thanks!
I can replicate this error if I fail to enclose the parameter in the call statement with single quotes.
Follow the correct code:
DELIMITER $
DROP PROCEDURE IF EXISTS REPORT$
CREATE PROCEDURE REPORT( IN_TAB_NAME VARCHAR(20) )
BEGIN
DECLARE sql_stmt VARCHAR(100);
BEGIN
SET #in_table = IN_TAB_NAME;
SET #sql_stmt = CONCAT(' SELECT [columns] FROM ' , #in_table,
' GROUP BY [column]');
SELECT #sql_stmt;
PREPARE stmt FROM #sql_stmt;
EXECUTE stmt;
END;
END$
DELIMITER ;
I am new to MySQl stored procedure. I am trying to create a simple procedure with single IN parameter with execution of simple prepare select statement. Am using IN parameter directly in select statement while creating PREPARE, this throwing Unknown column error for IN parameter on executing prepare statement.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_two$$
CREATE PROCEDURE test_prep_stmt_two(IN user_id_in INT)
BEGIN
#this line causing error
PREPARE param_stmt FROM "select * from users u where u.user_id=user_id_in";
EXECUTE param_stmt;
DEALLOCATE PREPARE param_stmt;
END $$
DELIMITER ;
DELIMITER $$
when I call procedure like CALL test_prep_stmt_two(1); am getting below error.
Error Code: 1054
Unknown column 'user_id_in' in 'where clause'
But if I set IN param value to any variable inside procedure and use that in prepare select statement then it's working fine. Below procedure is working fine.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_three$$
CREATE PROCEDURE test_prep_stmt_three(IN user_id_in INT)
BEGIN
SET #user_id_in=user_id_in;
#this works fine
PREPARE set_stmt FROM "select * from users u where u.user_id=#user_id_in";
EXECUTE set_stmt;
DEALLOCATE PREPARE set_stmt;
END $$
DELIMITER ;
Please, can anyone explain me why using IN parameter in prepare select statement throwing error.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_two$$
CREATE PROCEDURE test_prep_stmt_two(IN user_id_in INT)
BEGIN
SET #t1 = CONCAT("SELECT * FROM users u WHERE u.user_id = '", user_id_in, "'");
PREPARE param_stmt FROM #t1;
EXECUTE param_stmt;
DEALLOCATE PREPARE param_stmt;
END $$
DELIMITER ;
Try the above code. Hope this will help.
I've been trying to dynamically drop tables, procedures, and functions in MySQL. I'm doing this because I am dynamically creating them for a project, when the project version changes I need to clean up and rebuild it.
I can dynamically drop tables, however; I cannot dynamically drop procedures and functions.
Here is an example of the code I am using:
DELIMITER ;;
DROP PROCEDURE IF EXISTS md_remove_project; ;;
CREATE PROCEDURE md_remove_project()
begin
DECLARE TableName text;
DECLARE ProcName text;
DECLARE done int DEFAULT false;
DECLARE statement text;
DECLARE table_cursor CURSOR FOR
SELECT table_name FROM tmp_md_tables;
DECLARE proc_cursor CURSOR FOR
SELECT routine_name FROM tmp_md_procedures;
DECLARE func_cursor CURSOR FOR
SELECT routine_name FROM tmp_md_functions;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
# Drop all the 'md' tables..............................................
# This Works...
DROP TABLE IF EXISTS tmp_md_tables;
CREATE TEMPORARY TABLE tmp_md_tables
SELECT
table_name
FROM
information_schema.tables
WHERE
table_name LIKE 'md_%';
OPEN table_cursor;
table_loop: LOOP
FETCH table_cursor INTO TableName;
IF done THEN
LEAVE table_loop;
END IF;
SET #statement = CONCAT('DROP TABLE IF EXISTS ', TableName, ';');
PREPARE STATEMENT FROM #statement;
EXECUTE STATEMENT;
DEALLOCATE PREPARE STATEMENT;
END LOOP;
CLOSE table_cursor;
DROP TABLE IF EXISTS tmp_md_tables;
#-----------------------------------------------------------------------
# Drop all the 'md' procedures............................................
DROP TABLE IF EXISTS tmp_md_procedures;
CREATE TEMPORARY TABLE tmp_md_procedures
SELECT
routine_name
FROM
information_schema.routines
WHERE
routine_type = 'PROCEDURE'
and
routine_name LIKE 'md_%';
SET done = false;
OPEN proc_cursor;
proc_loop: LOOP
FETCH proc_cursor INTO ProcName;
IF ProcName = 'md_remove_project' THEN
ITERATE proc_loop;
END IF;
IF done THEN
leave proc_loop;
END IF;
SET #statement = CONCAT('DROP PROCEDURE IF EXISTS ', ProcName, ';');
PREPARE STATEMENT FROM #statement;
EXECUTE STATEMENT;
DEALLOCATE PREPARE STATEMENT;
END LOOP;
CLOSE proc_cursor;
DROP TABLE IF EXISTS tmp_md_procedures;
END;
;;
DELIMITER ;
#CALL md_remove_project;
So I create a table with the procedures named md_%, then I loop through the table. For each routine_name, I prepare a statement to drop the procedure. Then I get the following message:
Error Code: 1295. This command is not supported in the prepared statement protocol yet
Are there any other solutions to drop procedures like 'md_%' ???
Thank You.
When using mysqli_... functions, there is no need to attempt to change the delimiter. The change delimiter command is only needed when using the MySQL (command line) Client. The command is, in fact, a MySQL client command (the client never sends it to the server).
The server is smart enough to recognize the CREATE PROCEDURE command and knowns it ends with END;
As a result, you can simply do two queries: first the DROP PROCEDURE IF EXISTS ... followed by the CREATE PROCEDURE ... END; query.
If you must do them in a single call, you could use mysqli::multi_query but I would recommend against it (because of possible serious security implications).
I need to use a variable to indicate what database to query in the declaration of a cursor. Here is a short snippet of the code :
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SELECT cdrs_id, called, calling FROM dbName.cdrs WHERE lrn_checked = 'N';
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
As you can see, I'm TRYING to use the variable dbName to indicate in which database the query should occur within. However, MySQL will NOT allow that. I also tried things such as :
CREATE PROCEDURE `update_cdrs_lnp_data`(IN dbName VARCHAR(25), OUT returnCode SMALLINT)
cdr_records:BEGIN
DECLARE cdr_record_cursor CURSOR FOR
SET #query = CONCAT("SELECT cdrs_id, called, calling FROM " ,dbName, ".cdrs WHERE lrn_checked = 'N' ");
PREPARE STMT FROM #query;
EXECUTE STMT;
# Setup logging
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
#call log_debug('Got exception in update_cdrs_lnp_data');
SET returnCode = -1;
END;
Of course this doesn't work either as MySQL only allows a standard SQL statement in the cursor declaration.
Can anyone think of a way to use the same stored procedure in multiple databases by passing in the name of the db that should be affected?
The answer of Vijay Jadhav is the right way to solve this limitation by MySQL. Actually, you need 3 proc to accomplish it:
proc1 using Vijay Jadhav's way, works like a data collector. You need to pass the variables to proc1 and let it create the tmp table for proc2. There is one limiation of Vijay's way, he should create a TEMPORARY table by using "CREATE TEMPORARY TABLE tmp_table_name SELECT ...". Because temporary table is thread safe.
proc2 declare the cursor on the tmp table which is created by proc1. Since the tmp table is already known and hard coded into the declaration, no more "table not found" error.
proc3 works like a "main" function, with all the parameters need to be sent to proc1 and proc2. proc3 simply calls proc1 first and then proc2 with the parameters need by each proc.
p.s Need to set system variable "sql_notes" to 0, otherwise proc1 will stop on DROP TABLE command.
Here is my example:
CREATE PROCEDURE `proc1`(SourceDBName CHAR(50), SourceTableName CHAR(50))
BEGIN
DECLARE SQLStmt TEXT;
SET #SQLStmt = CONCAT('DROP TEMPORARY TABLE IF EXISTS tmp_table_name');
PREPARE Stmt FROM #SQLStmt;
EXECUTE Stmt;
DEALLOCATE PREPARE Stmt;
SET #SQLStmt = CONCAT('CREATE TEMPORARY TABLE tmp_table_name SELECT ... FROM ',SourceDBName,'.',SourceTableName,' WHERE ... ');
PREPARE Stmt FROM #SQLStmt;
EXECUTE Stmt;
DEALLOCATE PREPARE Stmt;
END$$
CREATE PROCEDURE `proc2`(TargetDBName CHAR(50), TargetTemplateTableName CHAR(50))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE FieldValue CHAR(50);
DECLARE CursorSegment CURSOR FOR SELECT ... FROM tmp_table_name;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN CursorSegment;
REPEAT
FETCH CursorSegment INTO FieldValue;
IF NOT done THEN
...
END IF;
UNTIL done END REPEAT;
CLOSE CursorSegment;
END$$
CREATE PROCEDURE `proc3`(SourceDBName CHAR(50), SourceTableName CHAR(50), TargetDBName CHAR(50), TargetTemplateTableName CHAR(50))
BEGIN
CALL proc1(SourceDBName, SourceTableName);
CALL proc2(TargetDBName, TargetTemplateTableName);
END$$
No, you can't do that in cursors.
Maybe just prepared statements may do the job? :
delimiter ;;
create procedure test(in dbName varchar(40))
begin
set #query := CONCAT("SELECT * FROM " , dbName, ".db;");
PREPARE s from #query;
EXECUTE s;
DEALLOCATE PREPARE s;
end;;
delimiter ;
call test("mysql");
Try to create (temporary) table using prepared statement in a different procedure.
SET #query = CONCAT("CREATE TABLE temp_table AS SELECT cdrs_id, called, calling FROM " ,dbName, ".cdrs WHERE lrn_checked = 'N' ");
...
And then select data from that table in your 'test' procedure.
The answer to this is that it cannot be done. You cannot use variables in the cursor declaration. I appreciate noonex's response. However, his solution does not allow me to walk through the results. It simply executes the query.
create procedure test(in dbName varchar(40))
READS SQL DATA <- this line returns will allow you to walk through the results
begin
...
$result = call test("mysql");