2013-07-05 45 views
0

我遇到了一個MySQL存儲過程非常有趣的問題。其過程如下:影響刪除的MySQL存儲過程變量名稱

DROP PROCEDURE IF EXISTS `removeSubscription`; 
DELIMITER ;; 
CREATE DEFINER=`root`@`%` PROCEDURE `removeSubscription`(IN `userId` int,IN `channelId` int,IN `channelTypeTitle` varchar(255)) 

BEGIN 

SET @userId = userId; 
SET @channelId = channelId; 
SET @channelTypeTitle = channelTypeTitle; 

DELETE FROM subscriptions 
WHERE 
    userid = @userId AND 
    channelid = @channelId AND 
    channeltypeid = (SELECT id FROM channeltypes WHERE `name` = @channelTypeTitle) 
LIMIT 1; 

END 
;; 
DELIMITER ; 

當這個被稱爲存儲過程從PHP,是忽略所有的「WHERE子句中,並簡單地刪除它遇到的第一行。這意味着,當「LIMIT 1」冷落,它刪除一切從表:■

這是PHP:

$stmt = $db->prepare("CALL removeSubscription(:userId, :channelId, :channelTypeTitle)"); 

$stmt->bindValue('userId', $userId); 
$stmt->bindValue('channelId', $channelId); 
$stmt->bindValue('channelTypeTitle', $channelTypeTitle); 

$stmt->execute(); 

奇怪的是,如果我在PHP都的重命名傳遞的參數準備並在存儲過程中(例如,在它們之前有一個'x'),那麼它就可以正常工作。我在這裏錯過了很明顯的東西嗎

+0

我可以看到「create procedure removeSubscription」語句嗎? –

+0

當然是@ SQL.injection - 我已經更新了原來的問題以包含CREATE語句 –

回答

2

不重用變量名的名稱在它們的作用域內應該是唯一的......並且不要在存儲過程中使用全局變量(它們具有全局作用域,因此您應該使用本地變量) ...

DROP PROCEDURE IF EXISTS `removeSubscription`; 
DELIMITER ;; 
CREATE DEFINER=`root`@`%` PROCEDURE `removeSubscription`(IN `userId` int,IN `channelId` int,IN `channelTypeTitle` varchar(255)) 

BEGIN 

declare userId_, channelId_, channelTypeTitle_ integer; 

SET userId_ = userId; 
SET channelId_ = channelId; 
SET channelTypeTitle_ = channelTypeTitle; 

DELETE FROM subscriptions 
WHERE 
    userid = userId_ AND 
    channelid = channelId_ AND 
    channeltypeid = (SELECT id FROM channeltypes WHERE `name` = channelTypeTitle_) 
LIMIT 1; 

END 
;; 
DELIMITER ; 
+0

我不明白爲什麼後綴變量名與_有什麼不同,前綴爲@。 @前綴是否使變量足夠獨特? –

+1

啊哈,我剛剛找到答案 - 他們是會話變量 - 請參閱[link](http://stackoverflow.com/questions/1009954/mysql-variable-vs-variable-whats-the-difference) –

+0

之前我真的可以考慮解決這個問題(......並且被我理解),下面的假設是否正確? 1 - 我使用的是全局變量(簡單的做法很糟糕),2 - 這些全局變量不區分大小寫,3 - MySQL查詢實際上是匹配行,因爲參數匹配了嗎? (所以,'channelid = @channelId'真的意味着'channelid = channelid') 這有道理嗎? –