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 相关文章推荐
left join、inner join、right join的区别
Apr 05 MySQL
MySQL root密码的重置方法
Apr 21 MySQL
MySQL Threads_running飙升与慢查询的相关问题解决
May 08 MySQL
解读MySQL的客户端和服务端协议
May 10 MySQL
MySql开发之自动同步表结构
May 28 MySQL
详解MySQL多版本并发控制机制(MVCC)源码
Jun 23 MySQL
MySQL的安装与配置详细教程
Jun 26 MySQL
SQL实现LeetCode(196.删除重复邮箱)
Aug 07 MySQL
MySQL悲观锁与乐观锁的实现方案
Nov 02 MySQL
Mysql事务索引知识汇总
Mar 17 MySQL
MySQL详细讲解变量variables的用法
Jun 21 MySQL
了解MySQL查询语句执行过程(5大组件)
Aug 14 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
将数组写入txt文件 var_export
2009/04/21 PHP
PHP模块 Memcached功能多于Memcache
2011/06/14 PHP
php可生成缩略图的文件上传类实例
2014/12/17 PHP
PHP数学运算与数据处理实例分析
2016/04/01 PHP
wordpress之js库集合研究介绍
2007/08/17 Javascript
使用AngularJS实现表单向导的方法
2015/06/19 Javascript
jQuery里filter()函数与find()函数用法分析
2015/06/24 Javascript
javascript数据结构之双链表插入排序实例详解
2015/11/25 Javascript
jQuery中trigger()与bind()用法分析
2015/12/18 Javascript
12个非常实用的JavaScript小技巧【推荐】
2016/05/18 Javascript
Jquery 自定义事件实现发布/订阅的简单实例
2016/06/12 Javascript
JavaScript实现网页头部进度条刷新
2017/04/16 Javascript
基于pako.js实现gzip的压缩和解压功能示例
2017/06/13 Javascript
javascript 初学教程及五子棋小程序的简单实现
2017/07/04 Javascript
js提取中文拼音首字母的封装工具类
2018/03/12 Javascript
说说如何在Vue.js中实现数字输入组件的方法
2019/01/08 Javascript
Jquery异步上传文件代码实例
2019/11/13 jQuery
详解vue之自行实现派发与广播(dispatch与broadcast)
2021/01/19 Vue.js
python实现对excel进行数据剔除操作实例
2017/12/07 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
python3 cvs将数据读取为字典的方法
2018/12/22 Python
利用matplotlib实现根据实时数据动态更新图形
2019/12/13 Python
Python中用pyinstaller打包时的图标问题及解决方法
2020/02/17 Python
django 扩展user用户字段inlines方式
2020/03/30 Python
CSS3简单实现照片墙
2014/12/12 HTML / CSS
Speedo速比涛中国官方网站:全球领先泳装运动品牌
2018/04/24 全球购物
应届毕业生自我鉴定范文
2013/12/27 职场文书
党员个人思想汇报
2013/12/28 职场文书
文明之星事迹材料
2014/05/09 职场文书
英语求职信范文
2014/05/23 职场文书
信访维稳工作汇报
2014/10/27 职场文书
2014年计生工作总结
2014/11/21 职场文书
归途列车观后感
2015/06/17 职场文书
运动会1000米加油稿
2015/07/21 职场文书
如何用PHP websocket实现网页实时聊天
2021/05/26 PHP
试用1103暨1103、1101同门大比武 [ DAIWEI ]
2022/04/05 无线电