Mysql中varchar字元串的比較,swoole預處理參數綁定
- 2019 年 12 月 15 日
- 筆記
寫在前面
事情起因:
使用了一個varchar類型的欄位儲存數字值。
在根據該欄位進行大小篩選的時候,出現該問題。
類似select * from sheets where s_status > 3
分析
php調用時條件傳的是數字類型
組件生成的SQL語句直接執行正常
排查
打開了mysql的運行日誌,分析到最終運行的sql語句大概如下
where s_status > '3'
使用的是php swoole,預處理。
解決有兩條路
- mysql的欄位類型改為數字
- 研究swoole的參數預處理問題,可以測試普通PHP的預處理是否也有問題
能學習的點
- 字元串類型欄位的比較規則
mysql中字元串類型欄位的比較規則
找了一圈資料,相關文章比較少,終於在比較不起眼的角落裡找到資料。
字元串比較 是根據ascii碼比較 只有當第一個字元相同才對比第二個字元。以此類推。 在線轉換ascii碼工具 https://www.iamwawa.cn/ascii.html
假設我們現在表中有2條欄位
id |
s_status |
s_name |
---|---|---|
1 |
4 |
測試1 |
2 |
258710588 |
測試2 |
如果按正常的sql執行 我篩選>3應該是2條結果都有,但是程式運行只能得到1條結果: id = 1的數據
那麼我們上面說到 字元串的比較規則,從第一個字元開始比較,只有第一個字元相等 才會比較第二個字元…
『4』 > 『3』 通過
字元 4 對應的ASCII碼為 52 字元 3 對應的ASCII碼為 51
『258710588』 > 『3』 不通過
字元 2 對應的ASCII碼為 50 字元 3 對應的ASCII碼為 51 此時已經有結果 不需要對比第二個字元
如果是』31』 > 『3』 也會通過
第一個字元相同,則對比第二個字元,而3沒有第二個字元了 所以是小於。
研究:php預處理時,參數綁定
// 省去連接等等 // 預處理及綁定 $stmt = $conn->prepare("SELECT * FROM `siam_test_bug` WHERE `s_wechat_cross_status` > ? "); $condition = 3; $stmt->bind_param("i", $condition); // 生成語句 > 3 $stmt->bind_param("s", $condition); // 生成語句 > '3' 就變成了字元串比較 不正常 $res = $stmt->execute(); $result = $stmt->get_result(); while ($myrow = $result->fetch_assoc()) { var_dump($myrow); echo "<br/>"; }
確定swoole
經過開發組內各位大哥的協助確定,是swoole的參數綁定,不支援決定類型,所以會出現這個坑。
已經提交swoole rfc 待解決