今天在使用Mysql的存儲過程處理數據的批量刪除時,遇到了WHERE條件中使用IN(strlist)時(strlist為逗號分隔的字符串),只有strlist的第一個元素才有效的問題,現在將問題和解決方法做下記錄。
我們首先創建兩張表userinfo(用戶信息表)和userextinfo(用戶擴展信息表),其中userextinfo表的UserID字段為外鍵對應userinfo表中的UserID字段
用戶信息表userinfo
初始數據
用戶擴展信息表userextinfo
初始數據
現在表中有6個用戶的信息,倘若我們現在需要根據用戶ID刪除用戶“老二”、“老三”和“老四”的數據,則需要先刪除userextinfo表中數據然后再刪除userinfo表中的數據。若在代碼中分別對三個用戶執行sql語句,先后刪除userextinfo和userinfo的信息,可以完成我們的目的。但是,當我們一次需要刪除的用戶越多時,在數據庫連接上的開銷就會增多。所以,我們現在可以采用存儲過程,用一次數據庫連接來完成這個操作。
錯誤的方式:
我們創建存儲過程P_User_Del
代碼如下:
1 TOP: BEGIN 2 DECLARE EXIT HANDLER FOR SQLEXCEPTION 3 BEGIN 4 ROLLBACK; 5 END; 6 7 START TRANSACTION; 8 9 IF LENGTH(ExtUserIds)>0 THEN 10 DELETE FROM userextinfo WHERE UserID IN(ExtUserIds); -- 刪除用戶擴展信息 11 DELETE FROM userinfo WHERE UserID IN(ExtUserIds); -- 刪除用戶信息 12 END IF; 13 14 COMMIT; 15 16 END
執行存儲過程,輸入參數“2,3,4”
存儲過程執行成功
此時,我們看到表中數據只刪除了“老二”的數據
這個問題是由於我們傳入的參數“ExtUserIds”是一個字符串,sql語句中的IN只能使用字符串中第一個逗號前的數據,所以在上面的例子中,只刪除了2號用戶的數據。
正確的方式:
當然,我們可以將字符串“ExtUserIds”按逗號分開,然后循環刪除信息,但是這么做會增加不少的邏輯處理。
現在我們不使用“IN”而使用“FIND_IN_SET”,將存儲過程修改為:
代碼如下:
1 TOP: BEGIN 2 DECLARE EXIT HANDLER FOR SQLEXCEPTION 3 BEGIN 4 ROLLBACK; 5 END; 6 7 START TRANSACTION; 8 9 IF LENGTH(ExtUserIds)>0 THEN 10 DELETE FROM userextinfo WHERE FIND_IN_SET(UserID,ExtUserIds); -- 刪除用戶擴展信息 11 DELETE FROM userinfo WHERE FIND_IN_SET(UserID,ExtUserIds); -- 刪除用戶信息 12 END IF; 13 14 COMMIT; 15 16 END
再次執行存儲過程,結果如下:
我們想要刪除的3個用戶信息全部清除掉了。
至於方法“FIND_IN_SET(str,strlist)”的其他應用場景大家可以自己查閱。