2011-06-07 61 views
4

我正在研究「分級」系統,並試圖確保一個人無法使用存儲過程兩次提交成績,人員在允許保存新等級之前對特定項目進行了評分。奇怪的是,我傳遞了一個用戶ID和對象ID,但是當我的存儲過程選擇了COUNT(*)時,我得到了錯誤的數字。MySql COUNT(*)在存儲過程中有所不同

這裏是我的存儲過程:

CREATE PROCEDURE `ADD_GRADE`(IN objectID int, IN grader int) 
BEGIN 
DECLARE gradeCount INT; 

SELECT COUNT(*) 
FROM GRADES 
WHERE Obj_ID = objectID AND Grader = grader 
INTO gradeCount; 

IF gradeCount <= 0 THEN INSERT INTO Grades (Obj_ID, Grader) VALUES (objectID, grader); 
END IF; 

if語句的工作,但由於某些原因,我的gradeCount似乎忽略了平地機ID,只是檢查基於Obj_ID。我已經添加了選項以確保我的參數保持在正確的值,並且它們是。如果我只複製選擇並在別處手動執行,我會得到正確的編號。

雖然是MySql的新手,但我並不陌生於SQL本身。我只是瘋了嗎?或者我做錯了什麼?

感謝

+1

不確定問題出在哪裏,但是你的邏輯太複雜了。 'COUNT(*)'不能返回<0(不能少於沒有行),所以你的測試應該是'IF gradecount <1 THEN INSERT'(IOW,如果這裏沒有一行存在,插入分級和obj_id)。 – 2011-06-07 20:21:39

回答

11

即使這個代碼工作(我不知道爲什麼它沒有),它不是以確保東西只需輸入一次的正確方法。

正確的方法是在objectID和分級器列上應用唯一約束。然後嘗試插入該行。如果行插入,則值是唯一的。如果你得到一個唯一的違規,那麼這些值已經輸入。

如果您沒有可用的唯一約束,則應該鎖定表以確保您的命令之間沒有其他更新發生。

7

我的猜測是因爲MySQL是案例字段名不區分大小寫,並且代碼

Grader = grader 

只是與自己比較之列,這是總是如此。您可能需要重命名您傳入的參數,以便它不具有與現有列相同的名稱。我通常讓所有的存儲過程參數都以__(偶數下劃線)繼續,所以我不會遇到像這樣的情況。

+0

我很喜歡這兩個答案。 Scott Bruns在最佳設計中是正確的,但你對這個問題的技術答案也是正確的。將列與自身進行比較正是發生的情況,並且計數將始終是Obj_ID等於對象ID的行數,因爲AND 1將始終評估爲true。 – 2011-06-07 20:58:07

+1

+1 Kibbee用於查看Grader = grader問題。這總是一些東西...... – 2011-06-07 21:05:18