记录 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