I use mysql workbench 6.2 for my database.
I created procedure to execute query string, But it error "syntax error unexpected" for variable 'declare #str varchar(2000)'. i try remove '#' in variable , but it is not effective in line 'PREPARE stmt FROM str;'. it notify error "unexpected str"
this is my code:
CREATE DEFINER=`root`#`localhost` PROCEDURE `new_procedure`()
BEGIN
declare #str varchar(2000) DEFAULT '';
set #str = 'select * from category;';
PREPARE stmt FROM #str;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Session variables are not declared. You do not need (and cannot do)
DECLARE #str varchar(2000) DEFAULT '';
only the set you already have is necessary
SET #str = 'select * from category;';
As an aside, it is best to name the session variables in situations like this something unique (in case the connection calling the procedure is already using the simple name for something else).
Related
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 dynamic query in stored procedure. my stored procedure is as follows:
CREATE PROCEDURE `test1`(IN tab_name VARCHAR(40),IN w_team VARCHAR(40))
BEGIN
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team=",w_team);
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END
when i try to run it with the following call:
call test1 ('Test','SPA');
i get the following error message:
Error Code: 1054. Unknown column 'SPA' in 'where clause'
i tested without where condition and it works fine, but with the where condition its not working, i tried using # with the variable name but it still does not work.
Thanks for your help.
Error Code: 1054. Unknown column 'SPA' in 'where clause'
This happens when you do not enclose input string within quotes, and SQL engine tries to identify it as a column in the table being queried. But it fails as it can't find it.
But what happens when it finds such column?
It fetches results when it finds some matches on the column values.
Obviously this is not what one was expecting.
How to overcome this? Use Prepared Statements with dynamic input values.
You can use placeholders like ? in stored procedures too on dynamic input values to use with Prepared Statements. The engine will handle escape characters and other string values when assigned to or compared within SQL expressions.
You just need to re-assign procedure inputs to one or more session variables, as required.
Example on your procedure:
CREATE PROCEDURE `test1`( IN tab_name VARCHAR(40), IN w_team VARCHAR(40) )
BEGIN
SET #t1 = CONCAT( 'SELECT * FROM ', tab_name, ' where team = ?' ); -- <-- placeholder
SET #w_team := w_team;
PREPARE stmt3 FROM #t1;
EXECUTE stmt3 USING #w_team; -- <-- input for placeholder
DEALLOCATE PREPARE stmt3;
END;
You missed to enclose the parameter w_team in WHERE clause.
Try like this:
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team='",w_team,"'");
Explanation:
Query from your code would be like:
SELECT * FROM Test where team=SPA
It will try find a column SPA which is not available, hence the error.
And we changed it to:
SELECT * FROM Test where team='SPA'
Try this..
CREATE PROCEDURE `test1`(IN tab_name VARCHAR(40),IN w_team VARCHAR(40))
BEGIN
SET #t1 =CONCAT("SELECT * FROM ",tab_name," where team='",w_team,"'");
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END
You are missing quotes around w_team variable..
you should print the statement that dynamically build so you can just copy printed statement and try so you can easily find this kind of problem.
select #t1 will print the statment that build dynamically..
you can add dynamic fields and condition by using CONCAT() MySQL function. I checked this is working fine.
DELIMITER $$
/*define procedure name*/
CREATE PROCEDURE getSearchData()
BEGIN
DECLARE conditions varchar(1000);
DECLARE selectField varchar(1000);
DECLARE SQL_QUERY varchar(1000);
/*define default select and condition*/
SET #selectField = 'status,id';
set #conditions = ' where return_flight=0';
SET #SQL_QUERY = CONCAT('SELECT ',#selectField, ' FROM flights ',#conditions);
/* you can add more select fields and conditions according to your requirement */
PREPARE stmt1 FROM #SQL_QUERY ;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END$$
DELIMITER ;
The error mysql is throwing is
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
My using phpmyadmin to wreite procedures.
and my stored procedure is
BEGIN
DECLARE page_limit int(100);
DECLARE page_no VARCHAR(100);
DECLARE rstarts int(100) DEFAULT 1;
DECLARE rends int(100) DEFAULT 15;
DECLARE query varchar(255) ;
set query = ' select brandid from brandinfo limit #rstarts,#rends';
PREPARE stmt FROM #query;
set rstarts = 15;
set rends =1;
EXECUTE stmt using #rstarts,#rends;
DEALLOCATE PREPARE stmt;
END
Declared variables and variables beginning with # are two different stories. Read about user defined variables (the ones with #).
DELIMITER $$
CREATE PROCEDURE your_procedure_name()
BEGIN
SET #rstarts = 1;
SET #rends = 15;
set #query = 'select brandid from brandinfo limit ?, ?';
PREPARE stmt FROM #query;
EXECUTE stmt using #rstarts, #rends;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
Also in your query string you want to use ? as parameters, not the variable names. And you might miss on setting the delimiter to something different than ;
I am getting syntax error on runnning this. Is it possible to use variables with limit without using concat function?
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ',_start,_end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Error is
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 '_qry;
EXECUTE stmt;
You missed , before the offset.
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
I think you have to change the DEFAULT DELIMITER first and adding PARAMETER DIRECTION before creating the STORED PROCEDURE.
There are good reasons to use prepared statements:
1. ) Save on query parsing
2.) Save on data conversion and copying
3.) Avoid SQL Injection
4.) Save memory on handling blobs
There are also drawbacks and chewats of using prepared statements:
1.) Query cache does not work
2.) Extra server round trip required if statement used only once
3.) Not all statements can be prepared. So you can’t use prepared API
exclusively you’ll need to fall back to normal API for some statements
4.) Newer and sometimes buggy code. I had a lot of problems with PHP
prepared statements. It is getting better but still it is less mature
than standard API
5.) You can’t use placeholders in place of all identifiers. For example you
can’t use them for table name. In certain version it even does not work for
LIMIT boundaries
6.) Inconvenient list handling. Unlike in for example PEAR emulated prepard
statements there is no nice way to pass list of values to IN
7.) Harder tracing. Logs were now fixed to include full statement text not
only “Execute” but in SHOW INNODB STATUS you would still see statements
without actual values – quite inonvenient for analyses.
try this one:
UPDATE 1
DELIMITER $$
CREATE PROCEDURE SP(IN _start INT,IN _end INT)
BEGIN
SET #iQuery = CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM #iQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
MySQL Syntax for Prepared Statements
delimiter //
drop procedure if exists SP //
create procedure SP(_start int,_end int)
begin
declare _qry varchar(500);
set #_qry = 'select * from tbl limit ?, ?';
set #start = _start;
set #end = _end;
prepare stmt from #qry;
execute stmt using #start, #end;
deallocate prepare stmt;
end; //
delimiter ;
call SP(1,2);
This is MySQL 5.1.
(Note: I realize there are better ways of doing this particular example, this is not my real code)
Here is what I want to do:
The below procedure gets created, but when I CALL it, I get "ERROR 1210 (HY000): Incorrect arguments to EXECUTE"
DELIMITER //
CREATE PROCEDURE get_users_by_state(IN state CHAR(2))
READS SQL DATA
BEGIN
SET #mystate = state;
SET #sql = CONCAT('SELECT * FROM test_table WHERE state = "?"');
PREPARE stmt FROM #sql;
EXECUTE stmt USING #mystate;
END;
//
CALL get_users_by_state('AA')//
ERROR 1210 (HY000): Incorrect arguments to EXECUTE
Is there a way to pass the procedure's parameters to the EXECUTE USING statement?
Here is a version that does indeed work, but irks me:
CREATE PROCEDURE get_users_by_state(IN state CHAR(2))
READS SQL DATA
BEGIN
SET #sql = CONCAT('SELECT * FROM test_table WHERE state = "', state, '"')
PREPARE stmt FROM #sql;
EXECUTE stmt;
END;
//
As a side-question, does MySQL have any facilities for escaping strings, like Postgres' quote_literal() and quote_ident()?
For a point of reference, here's something somewhat equivalent for Postgres:
CREATE OR REPLACE FUNCTION get_info_by_state(character)
RETURNS SETOF ret_type AS
$BODY$
DECLARE
sql text;
BEGIN
sql := 'SELECT uid, some_data FROM test_table WHERE state = ' || quote_literal($1);
RETURN QUERY EXECUTE sql;
END
$BODY$
LANGUAGE 'plpgsql' VOLATILE
Thanks!
I don't think you need double quotes around the parameter holder.
Update Here, lest there be no misunderstanding:
DELIMITER //
CREATE PROCEDURE get_users_by_state(IN state CHAR(2))
READS SQL DATA
BEGIN
SET #mystate = state;
SET #sql = CONCAT('SELECT * FROM test_table WHERE state = ?');
PREPARE stmt FROM #sql;
EXECUTE stmt USING #mystate;
END;
//