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 相关文章推荐
Mysql - 常用函数 每天积极向上
Apr 05 MySQL
浅谈Mysql多表连接查询的执行细节
Apr 24 MySQL
mysql 8.0.24版本安装配置方法图文教程
May 12 MySQL
MySQL 查询速度慢的原因
May 25 MySQL
MySQL中distinct和count(*)的使用方法比较
May 26 MySQL
MySQL 数据类型选择原则
May 27 MySQL
浅析MySQL如何实现事务隔离
Jun 26 MySQL
SQL实现LeetCode(176.第二高薪水)
Aug 04 MySQL
mysql 索引合并的使用
Aug 30 MySQL
WINDOWS下安装mysql 8.x 的方法图文教程
Apr 19 MySQL
详解Mysql事务并发(脏读、不可重复读、幻读)
Apr 29 MySQL
MySQL数据库之内置函数和自定义函数 function
Jun 16 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
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
兼容PHP和Java的des加密解密代码分享
2014/06/26 PHP
php获取从百度、谷歌等搜索引擎进入网站关键词的方法
2015/07/08 PHP
php调用云片网接口发送短信的实现方法
2017/10/25 PHP
最佳JS代码编写的14条技巧
2011/01/09 Javascript
jquery.validate分组验证代码
2011/03/17 Javascript
js 可拖动列表实现代码
2011/12/13 Javascript
使用JavaScript获取电池状态的方法
2014/05/03 Javascript
JavaScript类型系统之正则表达式
2016/01/05 Javascript
老生常谈Javascript中的原型和this指针
2016/10/09 Javascript
Javascript 高性能之递归,迭代,查表法详解及实例
2017/01/08 Javascript
JS实现图片高斯模糊切换效果的焦点图实例
2017/01/21 Javascript
Bootstrap的popover(弹出框)2秒后定时消失的实现代码
2017/02/27 Javascript
用node和express连接mysql实现登录注册的实现代码
2017/07/05 Javascript
vue .js绑定checkbox并获取、改变选中状态的实例
2018/08/24 Javascript
详解单页面路由工程使用微信分享及二次分享解决方案
2019/02/22 Javascript
Python生成随机数的方法
2014/01/14 Python
Python中数字以及算数运算符的相关使用
2015/10/12 Python
解析Python中while true的使用
2015/10/13 Python
python调用fortran模块
2016/04/08 Python
Python的Asyncore异步Socket模块及实现端口转发的例子
2016/06/14 Python
python django 增删改查操作 数据库Mysql
2017/07/27 Python
pandas 空的dataframe 插入列名的示例
2018/10/30 Python
详解python-图像处理(映射变换)
2019/03/22 Python
Tensorflow模型实现预测或识别单张图片
2019/07/19 Python
python爬虫之遍历单个域名
2019/11/20 Python
python的range和linspace使用详解
2019/11/27 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
2020/02/28 Python
CSS图片翻转动画技术详解(IE也实现了)
2014/04/03 HTML / CSS
Lenox官网:精美的瓷器&独特的礼品
2017/02/12 全球购物
中专毕业生自我鉴定
2014/02/02 职场文书
小学二年级评语
2014/04/21 职场文书
2014年教育实习工作总结
2014/11/22 职场文书
2016新教师岗前培训心得体会
2016/01/08 职场文书
php将xml转化对象的实例详解
2021/11/17 PHP
python 中的jieba分词库
2021/11/23 Python