記錄 MYSQL UPDATE AND 產生的問題
基於 Server version: 8.0.16 MySQL Community Server - GPL 版本
表結構數據初始化
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'a', '123');
INSERT INTO `t_user` VALUES (2, 'b', '123');
INSERT INTO `t_user` VALUES (3, 'c', '123');
查看數據
mysql> select * from t_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | a | 123 |
| 2 | b | 123 |
| 3 | c | 123 |
+----+----------+----------+
3 rows in set (0.00 sec)
如果想要將 id=1
的記錄更新成 username='e' password='456'
正常是這麼寫
update t_user set username = 'e', `password` = '456' where id = 1;
但是如果手抽了寫成
update t_user set username = 'e' and `password` = '2' where id = 1; -- 1
> 1292 - Truncated incorrect DOUBLE value: 'e'
一個 ,
和 and
的區別導致了不同的結果,並且將錯就錯將上面的 UPDATE AND 改寫下
update t_user set `password` = '456' and username = 'e' where id = 1; -- 2
> Affected rows: 1
結果更新成功了,但是並沒有按照預期,而是將 id=1
的 password
改爲了 0
mysql> select * from t_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | a | 0 |
| 2 | b | 123 |
| 3 | c | 123 |
+----+----------+----------+
3 rows in set (0.00 sec)
再來個變形
update t_user set `password` = '456' and username = 'a' where id = 1; -- 3
> Affected rows: 1
與上條對比只是改變了username的值,還是更新成功了,但是 password
被置爲了 1
mysql> select * from t_user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | a | 1 |
| 2 | b | 123 |
| 3 | 123 | c |
+----+----------+----------+
3 rows in set (0.00 sec)
結論:
如果將 ,
寫成了 and
其實是對 set 後的第一個字段進行賦值,而後面的and條件作爲邏輯運算,換種寫法更明瞭
update t_user set username = ('e' and `password` = '2') where id = 1; -- 1
update t_user set `password` = ('456' and username = 'e') where id = 1; -- 2
update t_user set `password` = ('456' and username = 'a') where id = 1; -- 3
對於第一種情況,e
不能作爲邏輯運算的條件所以報 Truncated incorrect DOUBLE value: 'xxx'
對於第二種情況,456
被當成 true (1), username = 'e'
不成立,所以右邊的條件爲 false (0),1 and 0 => 0 所以password
被置爲 0
對於第三種情況,456
被當成 true (1), username = 'a'
成立,所以右邊的條件爲 true (1),1 and 1 => 1 所以password
被置爲 1