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 重命名表的操作方法及注意事项
May 21 MySQL
mysql脏页是什么
Jul 26 MySQL
MySQL分库分表详情
Sep 25 MySQL
SQL优化老出错,那是你没弄明白MySQL解释计划用法
Nov 27 MySQL
解决MySQL添加新用户-ERROR 1045 (28000)的问题
Mar 03 MySQL
MySQL中IO问题的深入分析与优化
Apr 02 MySQL
CentOS MySql8 远程连接实战
Apr 19 MySQL
Mysql查询时间区间日期列表,不会由于数据表数据影响
Apr 19 MySQL
mysql 体系结构和存储引擎介绍
May 06 MySQL
MySQL详细讲解变量variables的用法
Jun 21 MySQL
MySQL下载安装配置详细教程 附下载资源
Sep 23 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
叶罗丽:为什么大家对颜冰这对CP非常关心,却对金茉两人十分冷漠
2020/03/17 国漫
Php做的端口嗅探器--可以指定网站和端口
2006/10/09 PHP
php中return的用法实例分析
2015/02/28 PHP
PHP在linux上执行外部命令的方法
2017/02/06 PHP
采用CSS和JS,刚好我最近有个站点要用到下拉菜单!
2006/06/26 Javascript
Javascript/Jquery——简单定时器的多种实现方法
2013/07/03 Javascript
js jquery获取随机生成id的服务器控件的三种方法
2013/07/11 Javascript
极力推荐10个短小实用的JavaScript代码段
2016/08/03 Javascript
JavaScript中清空数组的方法总结
2016/12/02 Javascript
Vue.js render方法使用详解
2017/04/05 Javascript
微信小程序 本地数据存储实例详解
2017/04/13 Javascript
Node.js简单入门前传
2017/08/21 Javascript
Angular4.0中引入laydate.js日期插件的方法教程
2017/12/25 Javascript
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
最全vue的vue-amap使用高德地图插件画多边形范围的示例代码
2020/07/17 Javascript
Python+Opencv识别两张相似图片
2020/03/23 Python
python机器学习理论与实战(六)支持向量机
2018/01/19 Python
Python操作Oracle数据库的简单方法和封装类实例
2018/05/07 Python
PyQt弹出式对话框的常用方法及标准按钮类型
2019/02/27 Python
使用Python OpenCV为CNN增加图像样本的实现
2019/06/10 Python
Python内置方法实现字符串的秘钥加解密(推荐)
2019/12/09 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
django的autoreload机制实现
2020/06/03 Python
美国第二大连锁书店:Books-A-Million
2017/12/28 全球购物
L’Artisan Parfumeur官网:法国香水品牌
2020/08/11 全球购物
汽车销售求职自荐信
2013/10/01 职场文书
数据管理员的自我评价分享
2013/11/15 职场文书
机械电子工程毕业生自荐信
2013/11/23 职场文书
舞蹈教育学专业推荐信
2013/11/27 职场文书
五好党支部事迹材料
2014/02/06 职场文书
《千年梦圆在今朝》教学反思
2014/02/24 职场文书
大学生自我评价200字(4篇)
2014/09/17 职场文书
交通事故委托书范本
2014/09/28 职场文书
2014年城管工作总结
2014/11/20 职场文书
java executor包参数处理功能 
2022/02/15 Java/Android
Python 匹配文本并在其上一行追加文本
2022/05/11 Python