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 表空间碎片的概念及相关问题解决
May 07 MySQL
MySQL sql_mode的使用详解
May 08 MySQL
MySQL中VARCHAR与CHAR格式数据的区别
May 26 MySQL
mysql 带多个条件的查询方式
Jun 05 MySQL
详细谈谈MYSQL中的COLLATE是什么
Jun 11 MySQL
MySQL 外键约束和表关系相关总结
Jun 20 MySQL
MySQL系列之九 mysql查询缓存及索引
Jul 02 MySQL
mysql中整数数据类型tinyint详解
Dec 06 MySQL
Mysql如何实现不存在则插入,存在则更新
Mar 25 MySQL
排查MySQL生产环境索引没有效果
Apr 11 MySQL
mysql 8.0.27 绿色解压版安装教程及配置方法
Apr 20 MySQL
MySql中的json_extract函数处理json字段详情
Jun 05 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下图片文字混合水印与缩略图实现代码
2009/12/11 PHP
php下网站防IP攻击代码,超级实用
2010/10/24 PHP
php中比较简单的导入phpmyadmin生成的sql文件的方法
2011/06/28 PHP
header跳转和include包含问题详解
2012/09/08 PHP
php实现图片缩放功能类
2013/12/18 PHP
PHP类中的魔术方法(Magic Method)简明总结
2014/07/08 PHP
php简单实现短网址(短链)还原的方法(测试可用)
2016/05/09 PHP
CakePHP框架Model关联对象用法分析
2017/08/04 PHP
PHP pthreads v3下同步处理synchronized用法示例
2020/02/21 PHP
event.srcElement+表格应用
2006/08/29 Javascript
扩展javascript的Date方法实现代码(prototype)
2010/11/20 Javascript
js 判断checkbox是否选中的实现代码
2010/11/23 Javascript
js获取单选框或复选框值及操作
2012/12/18 Javascript
原生JavaScript实现连连看游戏(附源码)
2013/11/05 Javascript
JS中Date日期函数中的参数使用介绍
2014/01/02 Javascript
Node.js实用代码段之正确拼接Buffer
2016/03/17 Javascript
详解JavaScript跨域总结与解决办法
2016/10/31 Javascript
微信小程序 textarea 详解及简单使用方法
2016/12/05 Javascript
vue返回上一页面时回到原先滚动的位置的方法
2018/12/20 Javascript
Python实现模拟登录及表单提交的方法
2015/07/25 Python
Python cookbook(数据结构与算法)在字典中将键映射到多个值上的方法
2018/02/18 Python
python实现C4.5决策树算法
2018/08/29 Python
利用Python求阴影部分的面积实例代码
2018/12/05 Python
Pandas统计重复的列里面的值方法
2019/01/30 Python
Django多数据库的实现过程详解
2019/08/01 Python
python实现按键精灵找色点击功能教程,使用pywin32和Pillow库
2020/06/04 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
Python浮点型(float)运算结果不正确的解决方案
2020/09/22 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
澳大利亚礼品卡商店:Gift Card Store
2019/06/24 全球购物
社会实践先进工作者事迹材料
2014/05/06 职场文书
讲文明懂礼貌演讲稿
2014/09/11 职场文书
2015年中学元旦晚会活动方案
2014/12/09 职场文书
预备党员自我评价范文
2015/03/04 职场文书
2015年“世界无车日”活动方案
2015/05/06 职场文书
python 对图片进行简单的处理
2021/06/23 Python