19

I'm using mysql and I need to somehow use the column curid returned by the prepared statement in the later query. I use prepared statements because as I've read, it is the only way to pass a variable to the LIMIT clause. I have this stored procedure here:

DROP PROCEDURE IF EXISTS fixbalance;
CREATE PROCEDURE fixbalance (userid INT)
 BEGIN
 DECLARE i INT DEFAULT 0;
 DECLARE balance INT DEFAULT 0;
 DECLARE idcnt INT;
 SET idcnt = (SELECT COALESCE(COUNT(id), 0) 
 FROM coupon_operations 
 WHERE user_id = userid);
 IF idcnt <> 0 THEN
 WHILE i <= idcnt DO
 BEGIN
 SET @iter = i;
 SET @user_id = userid; 
 SET @sql = CONCAT('SELECT id AS curid 
 FROM coupon_operations 
 WHERE user_id = ? 
 ORDER BY id ASC 
 LIMIT ?, 1');
 PREPARE stmt FROM @sql;
 EXECUTE stmt USING @user_id, @iter;
 DEALLOCATE PREPARE stmt;
 SET balance = balance + (SELECT points 
 FROM coupon_operations 
 WHERE user_id = @user_id 
 AND id = @curid);
 UPDATE coupon_operations SET balance = balance;
 SET i = i + 1;
 END;
 END WHILE;
 END IF;
END;
|

This does not work - I'm not sure how to pass the curid.

Sandeep Kumar M
4,6823 gold badges33 silver badges35 bronze badges
asked Mar 28, 2011 at 6:51

3 Answers 3

11

The solution was to SET the variable in the prepared statement itself as in:

SET @sql = CONCAT('SET @curid = SELECT id
 FROM coupon_operations 
 WHERE user_id = ? 
 ORDER BY id ASC 
 LIMIT ?, 1');
answered Mar 28, 2011 at 8:15
2
  • 1
    Whats's the point of CONCAT in the code above? Commented Apr 2, 2015 at 11:25
  • @Pacerier You don't need to use CONCAT unless you pass the table name or something as a parameter. ex) CONCAT('select * from ', the_table_name, ' where id>100'); Commented Jun 14, 2017 at 7:39
10

I'm glad you found your answer. Another solution would be to use the SELECT...INTO syntax:

SET @sql = CONCAT('SELECT id INTO @curid FROM coupon_operations 
 WHERE user_id = ? 
 ORDER BY id ASC 
 LIMIT ?, 1');
answered Mar 28, 2011 at 13:25
0

Please tried this. to solve Concatenate, PREPARE and EXECUTE statements as bellow..

CREATE DEFINER=`products`@`localhost` PROCEDURE `generateMeritList`(
 IN `mastercategory_id` INT(11), 
 IN `masterschools_id` INT(11)
 )
 NO SQL
 begin
 declare total int default 0;
 declare conditions varchar(255) default ''; 
 declare finalQuery varchar(60000) default '';
if mastercategory_id > 0 THEN
 SET conditions = CONCAT(' and app.masterschools_id = ', mastercategory_id);
end if;
SET @finalQuery = CONCAT(
 "SELECT * FROM applications app INNER JOIN masterschools school ON school.id = app.masterschools_id
WHERE 
 (app.status = 'active'", conditions, " LIMIT ",total); 
 PREPARE stmt FROM @finalQuery;
 EXECUTE stmt;
 DEALLOCATE PREPARE stmt;
end
answered May 7, 2016 at 7:35
1
  • This particular example is fine but I'd discourage using it as a general pattern due to risk of SQL injection. If the input was a string - such as VARCHAR - instead of INT, that'd potentially allow an attacker to inject SQL code. A properly-created prepared statement is safer than concatenating strings with external input. Commented Sep 27, 2019 at 7:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.