Làm thế nào để sử dụng các câu lệnh được chuẩn bị trong các thủ tục lưu trữ MySQL?


16

Tôi đang sử dụng mysql và tôi cần bằng cách nào đó sử dụng cột curid được trả về bởi câu lệnh đã chuẩn bị trong truy vấn sau này. Tôi sử dụng các câu lệnh đã chuẩn bị bởi vì như tôi đã đọc, đó là cách duy nhất để chuyển một biến sang mệnh đề LIMIT. Tôi có thủ tục lưu trữ này ở đây:

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;
|

Điều này không hoạt động - Tôi không chắc chắn làm thế nào để vượt qua đường cong.

Câu trả lời:


10

Giải pháp là thiết lập biến trong chính câu lệnh đã chuẩn bị như sau:

SET @sql = CONCAT('SET @curid = SELECT id
                                FROM coupon_operations 
                                WHERE user_id = ? 
                                ORDER BY id ASC 
                                LIMIT ?, 1');

1
Điểm CONCATtrong mã ở trên là gì?
Pacerier

@Pacerier Bạn không cần sử dụng CONCATtrừ khi bạn vượt qua tên bảng hoặc một cái gì đó làm tham số. ví dụ)CONCAT('select * from ', the_table_name, ' where id>100');
Deckard

9

Tôi rất vui vì bạn đã tìm thấy câu trả lời của bạn. Một giải pháp khác là sử dụng cú pháp CHỌN ... VÀO :

SET @sql = CONCAT('SELECT id INTO @curid FROM coupon_operations 
                   WHERE user_id = ? 
                   ORDER BY id ASC 
                   LIMIT ?, 1');

0

Hãy thử nó. để giải quyết các câu lệnh Concatenate, PREPARE và EXECUTE dưới đây ..

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

Ví dụ cụ thể này là tốt nhưng tôi không khuyến khích sử dụng nó làm mẫu chung do rủi ro của việc tiêm SQL . Nếu đầu vào là một chuỗi - chẳng hạn như VARCHAR - thay vì INT, điều đó có khả năng cho phép kẻ tấn công tiêm mã SQL. Một câu lệnh được chuẩn bị được tạo đúng sẽ an toàn hơn so với các chuỗi nối với đầu vào bên ngoài.
Juanal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.