MySQL update set 和 and的区别


Posted in MySQL onMay 08, 2021

问题描述

最近接到一个奇怪的咨询,update 语句执行没有报错,但是没有更新数据,具体有问题的语句类似于如下形式:

update test.stu set cname = '0' and math = 90 and his = 80 where id = 100;

原因分析

直观上看,这个 update 语句的语法是有问题的,正常更新多列数据的语法应该是用逗号,类似于如下形式:

update test.stu set cname = '0',math = 90,his = 80 where id = 100;

直接用 and 第一反应其实是会报语法错误,不太像是能正常执行的。那么基于腾讯云数据库 MySQL,实际构造一个简单的场景,尝试复现一下这个问题。

SQL 语句如下:

CREATE TABLE `stu` (
  `id` int(11) NOT NULL,
  `sname` varchar(16) NOT NULL,
  `cname` varchar(8) DEFAULT NULL,
  `math` int(11) NOT NULL,
  `eng` int(11) DEFAULT NULL,
  `his` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into stu values(100,'sam','0',90,88,83);
insert into stu values(101,'jhon','1',97,82,81);
insert into stu values(102,'mary','2',87,89,92);
insert into stu values(103,'adam','2',87,89,92);

然后分别试一试正常的 update 语句和使用 and 的 update 语句,看一下实际的运行结果:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test.stu set cname = '0' and math = 90 and his = 80 where id = 100;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

mysql> select * from stu;
+-----+-------+-------+------+------+------+
| id  | sname | cname | math | eng  | his  |
+-----+-------+-------+------+------+------+
| 100 | sam   | 0     |   90 |   88 |   83 |
| 101 | jhon  | 1     |   97 |   82 |   81 |
| 102 | mary  | 2     |   87 |   89 |   92 |
| 103 | adam  | 2     |   87 |   89 |   92 |
+-----+-------+-------+------+------+------+
4 rows in set (0.00 sec)

mysql> update test.stu set cname = '0',math = 90,his = 80 where id = 100;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from stu;
+-----+-------+-------+------+------+------+
| id  | sname | cname | math | eng  | his  |
+-----+-------+-------+------+------+------+
| 100 | sam   | 0     |   90 |   88 |   80 |
| 101 | jhon  | 1     |   97 |   82 |   81 |
| 102 | mary  | 2     |   87 |   89 |   92 |
| 103 | adam  | 2     |   87 |   89 |   92 |
+-----+-------+-------+------+------+------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.01 sec)

mysql>

可以看到这两个语句确实都不会报错,且带 and 的 update 语句匹配到了具体的行(Rows matched: 1),但是没有修改数据(Changed: 0),标准语法下的 update 语句倒是正常修改了数据。

由此可见,MySQL 在语法上,并不认为 and 这个用法是错误的,那么说明 MySQL 用另外的方式“解读”了这个语句。最容易想到的,就是 MySQL 是不是在 set 的时候,把 and 解释成了逻辑运算符,而不是英文意义上的“和”?而且 cname 的取值本来就是 0,也符合数据库处理 bool 数据时的行为(用 0 和 1 代替 False 和 True)。

验证起来很简单,换个 cname 不为 0 的数据 update 一下就可以了:

mysql> select * from stu;
+-----+-------+-------+------+------+------+
| id  | sname | cname | math | eng  | his  |
+-----+-------+-------+------+------+------+
| 100 | sam   | 0     |   90 |   88 |   83 |
| 101 | jhon  | 1     |   97 |   82 |   81 |
| 102 | mary  | 2     |   87 |   89 |   92 |
| 103 | adam  | 2     |   87 |   89 |   92 |
+-----+-------+-------+------+------+------+
4 rows in set (0.00 sec)

mysql> begin;update test.stu set cname = '0' and math = 90 and his = 80 where id = 101;
Query OK, 0 rows affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from stu;
+-----+-------+-------+------+------+------+
| id  | sname | cname | math | eng  | his  |
+-----+-------+-------+------+------+------+
| 100 | sam   | 0     |   90 |   88 |   83 |
| 101 | jhon  | 0     |   97 |   82 |   81 |
| 102 | mary  | 2     |   87 |   89 |   92 |
| 103 | adam  | 2     |   87 |   89 |   92 |
+-----+-------+-------+------+------+------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

从结果来看,MySQL 修改 cname 的值为 0,说明确实是当成逻辑运算符来处理了,仔细分析这个语句,会发现 MySQL 按照如下方式来处理:

set cname = ('0' and math = 90 and his = 80)

math 和 his 的取值是根据 where 条件筛选的行来决定的,实际对应到上面测试的场景,会变成如下的逻辑判断:

'0' and 97 = 90 and 81 = 80

PS:需要注意,即便是字符型的数据 0,也会被当做 False。

解决方案

目前并不能通过 sql_mode 或者其他参数的形式来阻止这种带 and 的 update 语句,因此这一类问题的隐蔽性比较强。建议在开发的时候,利用封装好的框架,或者加强代码或者 SQL review 来避免这个问题。

PS:腾讯云数据库 MySQL 也会有类似的问题,需要警惕。

以上就是MySQL update set 和 and的区别的详细内容,更多关于MySQL update set 和 and的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
数据库的高级查询六:表连接查询:外连接(左外连接,右外连接,UNION关键字,连接中ON与WHERE的不同)
Apr 05 MySQL
MySQL 自定义变量的概念及特点
May 13 MySQL
详解MySQL中的主键与事务
May 27 MySQL
MySQL索引失效的典型案例
Jun 05 MySQL
MySQL系列之十五 MySQL常用配置和性能压力测试
Jul 02 MySQL
SQL基础的查询语句
Nov 11 MySQL
浅谈MySql整型索引和字符串索引失效或隐式转换问题
Nov 20 MySQL
MySQL日期时间函数知识汇总
Mar 17 MySQL
MySQL RC事务隔离的实现
Mar 31 MySQL
MySQL分区路径子分区再分区
Apr 13 MySQL
MySQL 执行数据库更新update操作的时候数据库卡死了
May 02 MySQL
mysql查找连续出现n次以上的数字
May 11 MySQL
MySQL查询学习之基础查询操作
May 08 #MySQL
MySQL sql_mode修改不生效的原因及解决
May 07 #MySQL
一篇文章弄懂MySQL查询语句的执行过程
详解MySQL主从复制及读写分离
MySQL 表空间碎片的概念及相关问题解决
MySQL kill不掉线程的原因
May 07 #MySQL
MySQL数字类型自增的坑
May 07 #MySQL
You might like
一个简单的PHP入门源程序
2006/10/09 PHP
php中url传递中文字符,特殊危险字符的解决方法
2013/08/17 PHP
destoon会员注册提示“数据校验失败(2)”解决方法
2014/06/21 PHP
详解PHP素材图片上传、下载功能
2019/04/12 PHP
小试JQuery的AutoComplete插件
2011/05/04 Javascript
JS 控制小数位数的实现代码
2011/08/02 Javascript
javascript中数组的sort()方法的使用介绍
2013/12/18 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
2016/09/05 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
JS中用EL表达式获取上下文参数值的方法
2018/03/28 Javascript
webpack配置打包后图片路径出错的解决
2018/04/26 Javascript
示例vue 的keep-alive缓存功能的实现
2018/12/13 Javascript
[42:25]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第三场
2018/04/06 DOTA
CentOS中使用virtualenv搭建python3环境
2015/06/08 Python
python中如何使用正则表达式的集合字符示例
2017/10/09 Python
matplotlib绘图实例演示标记路径
2018/01/23 Python
java中两个byte数组实现合并的示例
2018/05/09 Python
Python定义二叉树及4种遍历方法实例详解
2018/07/05 Python
Python初学者需要注意的事项小结(python2与python3)
2018/09/26 Python
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
Python正则表达式匹配数字和小数的方法
2019/07/03 Python
Django项目使用CircleCI的方法示例
2019/07/14 Python
face++与python实现人脸识别签到(考勤)功能
2019/08/28 Python
conda安装tensorflow和conda常用命令小结
2021/02/20 Python
CSS去掉A标签(链接)虚线框的方法
2014/04/01 HTML / CSS
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
英国Boots旗下太阳镜网站:Boots Designer Sunglasses
2018/07/07 全球购物
在阿联酋购买翻新手机和平板电脑:Teckzu
2021/02/12 全球购物
高级护理专业毕业生推荐信
2013/12/25 职场文书
校园报刊亭创业计划书
2014/01/02 职场文书
禁毒宣传标语
2014/06/19 职场文书
2014镇党委班子对照检查材料思想汇报
2014/09/23 职场文书
2015年医德医风工作总结
2015/04/02 职场文书
交心谈心活动总结
2015/05/11 职场文书
React + Threejs + Swiper 实现全景图效果的完整代码
2021/06/28 Javascript
解决Mysql报错 Table 'mysql.user' doesn't exist
2022/05/06 MySQL