MySQL 저장 프로 시저 내에서 준비된 명령문을 사용하는 방법은 무엇입니까?


16

mysql을 사용하고 있으며 나중에 쿼리에서 준비된 문에 의해 반환 된 열 curid를 사용해야합니다. 읽은대로 변수를 LIMIT 절에 전달할 수있는 유일한 방법이기 때문에 준비된 명령문을 사용합니다. 이 저장 프로 시저가 여기 있습니다.

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

작동하지 않습니다. 커드를 전달하는 방법을 잘 모르겠습니다.

답변:


10

해결책은 다음과 같이 준비된 명령문 자체에서 변수를 설정하는 것입니다.

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

1
CONCAT위의 코드에서 요점은 무엇입니까?
Pacerier

@Pacerier CONCAT테이블 이름이나 다른 것을 매개 변수로 전달하지 않으면 사용할 필요가 없습니다 . 예)CONCAT('select * from ', the_table_name, ' where id>100');
Deckard

9

답변을 찾게되어 기쁩니다. 또 다른 해결책은 SELECT ... INTO 구문 을 사용하는 것입니다 .

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

0

이것을 시도하십시오. 연결, PREPARE 및 EXECUTE 문을 다음과 같이 해결하는 방법

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

이 특정 예제는 훌륭하지만 SQL 삽입 위험 으로 인해 일반적인 패턴으로 사용하지 않는 것이 좋습니다 . 입력이 INT 대신 문자열 (예 : VARCHAR) 인 경우 공격자가 SQL 코드를 삽입 할 수 있습니다. 올바르게 작성된 준비된 명령문은 외부 입력으로 문자열을 연결하는 것보다 안전합니다.
Juanal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.