what is wrong with MySQL select Store Procedure with dynamic query - mysql

i have tried to create MySQL store procedure in that i want to make dynamic query.
code on which i working..
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`selectp` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `selectp`(in a_str_Condition varchar(500))
BEGIN
SET #Query = 'SELECT * from test123';
IF a_str_Condition != ''
THEN
SET #strCondition = CONCAT(' WHERE ? ');
SET #param = a_str_Condition;
ELSE
SET #strCondition = ' Order by aaa desc';
END IF
SET #Query = CONCAT(#Query, #strCondition );
PREPARE stmt FROM #Query;
EXECUTE stmt USING #param;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
here i want pass parameter as aaa = 3 and concat it with mysql query, but it show me error as below.
please let me clear on this store procedure. Any help will be Appreciate.

Trying to answer to your ...what is wrong with MySQL select Store Procedure..?
As others mentioned you have ; missing. That only solves a syntax error.
But you have bigger problems with the way you try to construct your query and EXECUTE it:
You're incorrectly trying to treat all where conditions as one parameter with WHERE ?, instead of parameterizing values like WHERE id = ?
In case you don't pass a condition you can't use USING in EXECUTE. It'll fail.
Now since you don't execute your query multiple times, you pass conditions as a string anyway, and it seems that you're more after flexibility than security, IMHO there is no much sense in using parameters here.
That being said a more succinct version of your SP might look like this
DELIMITER $$
CREATE PROCEDURE selectp(IN _conditions VARCHAR(500), IN _orderby VARCHAR(500))
BEGIN
SET #sql = CONCAT(
'SELECT * FROM test123 WHERE 1 = 1',
COALESCE(CONCAT(' AND ', NULLIF(_conditions, '')), ''),
' ORDER BY ',
COALESCE(NULLIF(_orderby, ''), 'id DESC')
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Usage examples:
-- default parameters either with null or an empty string
CALL selectp('', '');
CALL selectp(NULL, NULL);
-- set where conditions
CALL selectp('id IN(1, 3)', NULL);
-- set order by
CALL selectp(NULL, 'col1 DESC, col2');
Here is SQLFiddle demo

You've lost a semicolon after END IF.
And that's what mysql is pointed you to - it always shows you the expression part it couldn't parse. So always look at the code right before the one from the error description.

There should be a semi column after the END IF statement:
ELSE
SET #strCondition = ' Order by aaa desc';
END IF; //add semicolumn here
Before this line:
SET #Query = CONCAT(#Query, #strCondition );

Related

MySQL prepared statements with parameters not returning data

I have been trying to make parameterized prepared statements work. The first function only presents the header row with the column names and does not show any daya. The second
function provides all the data requested. The difference is that the first one uses parameters and the second only uses concatenated strings. The select statements in the first
function are used for debugging purposes, there are no NULL strings in any of the variables.
I would like to get the parameterized version working properly, I would appreciate any help.
I have already checked out these stackoverflow answers, Multiple Parameters, mysql Prepare Statement, Internals of prepared statement, unable to create prepared statements (might be the answer to my problem).
-- -----------------------------------------------------
-- procedure getAllBookDataWhere2
-- -----------------------------------------------------
USE `booklibinventory`;
DROP procedure IF EXISTS `booklibinventory`.`getAllBookDataWhere2`;
DELIMITER $$
USE `booklibinventory`$$
CREATE PROCEDURE `getAllBookDataWhere2`
(
IN whereStr VARCHAR(256)
)
BEGIN
DECLARE finalQuery VARCHAR(4096);
DECLARE selectedFields, leftJoinTables, joinOnFields VARCHAR(1024);
DECLARE whereClause, orderByClause VARCHAR(256);
SET #selectedFields = allBooksSelectFields();
SET #jointTables4Query = allBooksDataTables();
-- orderBy may become a parameter in the future.
SET #orderByClause = ' a.LastName, a.FirstName, s.SeriesName, v.VolumeNumber, t.TitleStr';
SET #whereclause = whereStr;
-- #selectedFields and #jointTables4Query are concatenated because they don't change,
-- #whereClause and #orderByClause can change and therefore are parameters.
SELECT #orderByClause;
SELECT #whereClause;
SET #finalQuery = CONCAT('SELECT ', #selectedFields);
SET #finalQuery = CONCAT(#finalQuery, ' FROM bookinfo AS BKI ');
SET #finalQuery = CONCAT(#finalQuery, #jointTables4Query);
SET #finalQuery = CONCAT(#finalQuery, ' WHERE ? ORDER BY ? ;');
SELECT #finalQuery;
PREPARE stmt FROM #finalQuery;
EXECUTE stmt USING #whereClause, #orderByClause;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
-- -----------------------------------------------------
-- procedure getAllBookDataWhere
-- -----------------------------------------------------
USE `booklibinventory`;
DROP procedure IF EXISTS `booklibinventory`.`getAllBookDataWhere`;
DELIMITER $$
USE `booklibinventory`$$
CREATE PROCEDURE `getAllBookDataWhere`
(
IN whereStr VARCHAR(256)
)
BEGIN
DECLARE finalQuery VARCHAR(4096);
DECLARE selectedFields, leftJoinTables, joinOnFields VARCHAR(1024);
DECLARE whereClause, orderByClause VARCHAR(256);
SET #selectedFields = allBooksSelectFields();
SET #jointTables4Query = allBooksDataTables();
-- orderBy may become a parameter in the future.
SET #orderByClause = ' ORDER BY a.LastName, a.FirstName, s.SeriesName, v.VolumeNumber, t.TitleStr;';
SET #whereclause = CONCAT(' WHERE ', whereStr);
-- #selectedFields and #jointTables4Query are concatenated because they don't change,
-- #whereClause and #orderByClause can change and therefore are parameters.
SET #finalQuery = CONCAT('SELECT ', #selectedFields);
SET #finalQuery = CONCAT(#finalQuery, ' FROM bookinfo AS BKI ');
SET #finalQuery = CONCAT(#finalQuery, #jointTables4Query);
SET #finalQuery = CONCAT(#finalQuery, #whereClause);
SET #finalQuery = CONCAT(#finalQuery, #orderByClause);
PREPARE stmt FROM #finalQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Parameters are for values, not whole clauses. Your WHERE and ORDER BY clauses are effectively WHERE 'somestring' and ORDER BY 'somestring' (note the quotes).
Also, if I remember correctly, EXECUTEd statements do not add resultsets to a procedure's returned results; typically, the execute ends up needing to be an insert select into a temporary table that the procedure can select from directly before exiting.
Edit: Since you're already concat-ing the query together, you could just replace your ?-placeholders, ... WHERE ', #whereClause, ' ORDER BY ', #orderByClause, ';');
Parameters can't protect you from letting raw sql be "user" supplied.

Calling stored procedure with a string to use in query

I have a stored procedure where i need to pass a string to use in the query.
Stored procedure example:
BEGIN
SET #query = query;
SELECT * FROM test WHERE #query
END
How I would like to call it with a string:
CALL proceduretet('activity_id = 1 OR activity_id = 2')
The query can be different each time, sometimes there will be 1 activity_id and sometimes 4 or more.
I have tried to pass it as a varchar and text, but it won't work.
So is there a way to pass a string to stored procedures and use it in the query?
Regards, Andreas
The code would look like:
BEGIN
SET #query = query;
SET #sql = concat('SELECT * FROM TEST WHERE ', #query);
PREPARE stmt from #sql;
EXECUTE stmt;
END;

how to define a stored procedures which accepts 2 parameteres

I´m trying to define a stored procedures which accepts 2 parameteres , one would be the table column which has to be equal with the second parameter i will provide.
Code :
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `selectUserByField`(IN _field varchar(150) , IN _value varchar(150))
BEGIN
SET #sql = CONCAT('SELECT * FROM Users WHERE', _field, '=' ,_value);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
The thing is that i don´t know how to provide the _value param as a string. If i run it like this i get a Mysql 1064 near ´=myEmail´( params where ´userEmail´,´myEmail´). Thanks !
In your below code, you are missing a space after WHERE. It should be like below; give a space after WHERE and in =
SET #sql = CONCAT('SELECT * FROM Users WHERE ', _field, ' = ' ,_value);

Can I use a String as a WHERE CLAUSE

Can anybody help me with this JSP problem.
Im trying to update the database using code similar to this:
So, I have this on my Servlet:
String QueryCondition = "id = 1";
That will be passed to this stored procedure:
CREATE
DEFINER=`root`#`localhost`
PROCEDURE `storedprocedure_1`(QueryCondition TEXT)
BEGIN
UPDATE users SET name = 'John'
WHERE QueryCondition;
END
I was thinking if this is possible because the update always fail.
If this isn't possible can you recommend how can i do such thing
You can use it in a stored procedure but with a prepared statement.
Example:
DELIMITER //
CREATE
DEFINER=root#localhost
PROCEDURE storedprocedure_1(QueryCondition TEXT)
BEGIN
SET #query := CONCAT( 'UPDATE users SET name = \'John\' WHERE ',
QueryCondition );
PREPARE stmt FROM #query;
EXECUTE stmt;
DROP PREPARE stmt;
END;
//
DELIMITER ;

use a variable for table name in mysql sproc

I'm trying to pass a table name into my mysql stored procedure to use this sproc to select off of different tables but it's not working...
this is what I"m trying:
CREATE PROCEDURE `usp_SelectFromTables`(
IN TableName varchar(100)
)
BEGIN
SELECT * FROM #TableName;
END
I've also tried it w/o the # sign and that just tells me that TableName doesn't exist...which I know :)
SET #cname:='jello';
SET #vname:='dwb';
SET #sql_text = concat('select concept_id,concept_name,',#vname,' from enc2.concept a JOIN enc2.ratings b USING(concept_id) where concept_name like (''%',#cname,'%'') and 3 is not null order by 3 asc');
PREPARE stmt FROM #sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
An extra bit that caused me problems.
I wanted to set the table name and field dynamically in a query as #kyle asked, but I also wanted to store the result of that query into a variable #a within the query.
Instead of putting the variable #a into the concat literally, you need to include it as part of the string text.
delimiter //
CREATE PROCEDURE removeProcessed(table_name VARCHAR(255), keyField VARCHAR(255), maxId INT, num_rows INT)
BEGIN
SET #table_name = table_name;
SET #keyField = keyField;
SET #maxId = maxId;
SET #num_rows = num_rows;
SET #sql_text1 = concat('SELECT MIN(',#keyField,') INTO #a FROM ',#table_name);
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
loop_label: LOOP
SET #sql_text2 = concat('SELECT ',#keyField,' INTO #z FROM ',#table_name,' WHERE ',#keyField,' >= ',#a,' ORDER BY ',#keyField,' LIMIT ',#num_rows,',1');
PREPARE stmt2 FROM #sql_text2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
...Additional looping code...
END LOOP;
END
//
delimiter ;
So in #sql_text1 assign the result of the query to #a within the string using:
') INTO #a FROM '
Then in #sql_text2 use #a as an actual variable:
,' WHERE ',#keyField,' >= ',#a,' ORDER BY '
It depends on the DBMS, but the notation usually requires Dynamic SQL, and runs into the problem that the return values from the function depend on the inputs when it is executed. This gives the system conniptions. As a general rule (and therefore probably subject to exceptions), DBMS do not allow you to use placeholders (parameters) for structural elements of a query such as table names or column names; they only allow you to specify values such as column values.
Some DBMS do have stored procedure support that will allow you to build up an SQL string and then work with that, using 'prepare' or 'execute immediate' or similar operations. Note, however, that you are suddenly vulnerable to SQL injection attacks - someone who can execute your procedure is then able to control, in part, what SQL gets executed.