Bagaimana cara menggunakan pernyataan yang disiapkan dalam prosedur tersimpan MySQL?

16

Saya menggunakan mysql dan saya perlu entah bagaimana menggunakan kolom curid yang dikembalikan oleh pernyataan yang disiapkan dalam permintaan nanti. Saya menggunakan pernyataan yang telah disiapkan karena seperti yang saya baca, ini adalah satu-satunya cara untuk meneruskan variabel ke klausa LIMIT. Saya memiliki prosedur tersimpan ini di sini:

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

Ini tidak berfungsi - Saya tidak yakin bagaimana cara melewatkan curid.

donk
sumber

Jawaban:

10

Solusinya adalah dengan SET variabel dalam pernyataan yang disiapkan itu sendiri seperti pada:

SET @sql = CONCAT('SET @curid = SELECT id
                                FROM coupon_operations 
                                WHERE user_id = ? 
                                ORDER BY id ASC 
                                LIMIT ?, 1');
donk
sumber
1
Apa gunanya CONCATkode di atas?
Pacerier
@Pacerier Anda tidak perlu menggunakan CONCATkecuali Anda memasukkan nama tabel atau sesuatu sebagai parameter. ex)CONCAT('select * from ', the_table_name, ' where id>100');
Deckard
9

Saya senang Anda menemukan jawaban Anda. Solusi lain adalah dengan menggunakan sintaks SELECT ... INTO :

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

Silakan coba ini. untuk menyelesaikan pernyataan Concatenate, PREPARE dan EXECUTE seperti di bawah ini ..

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
Dinesh Vaitage
sumber
Contoh khusus ini baik-baik saja tapi saya akan mencegah menggunakannya sebagai pola umum karena risiko injeksi SQL . Jika inputnya berupa string - seperti VARCHAR - alih-alih INT, itu akan berpotensi memungkinkan penyerang menyuntikkan kode SQL. Pernyataan yang disiapkan dengan benar dibuat lebih aman daripada merangkai string dengan input eksternal.
Juanal