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 相关文章推荐
JDBC连接的六步实例代码(与mysql连接)
May 12 MySQL
MYSQL主从数据库同步备份配置的方法
May 26 MySQL
MySql 缓存查询原理与缓存监控和索引监控介绍
Jul 02 MySQL
MySQL系列之十一 日志记录
Jul 02 MySQL
mysql备份策略的实现(全量备份+增量备份)
Jul 07 MySQL
解决mysql的int型主键自增问题
Jul 15 MySQL
mysql脏页是什么
Jul 26 MySQL
关于MySQL临时表为什么可以重名的问题
Mar 22 MySQL
Mysql如何实现不存在则插入,存在则更新
Mar 25 MySQL
MySQL事务操作的四大特性以及并发事务问题
Apr 12 MySQL
MySQL中dd::columns表结构转table过程及应用详解
Sep 23 MySQL
mysql序号rownum行号实现方式
Dec 24 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自定义函数call_user_func和call_user_func_array详解
2011/07/14 PHP
Django 中 cookie的使用
2017/08/17 PHP
PHP PDOStatement::getAttribute讲解
2019/02/01 PHP
Smarty模板语法详解
2019/07/20 PHP
浅析PHP中的 inet_pton 网络函数
2019/12/16 PHP
input的focus方法使用
2010/03/13 Javascript
JQuery操作三大控件(下拉,单选,复选)的方法
2013/08/06 Javascript
js设置function参数默认值(适合没有传参情况)
2014/02/24 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
分享javascript计算时间差的示例代码
2020/03/19 Javascript
如何将 jQuery 从你的 Bootstrap 项目中移除(取而代之使用Vue.js)
2017/07/17 jQuery
vue项目tween方法实现返回顶部的示例代码
2018/03/02 Javascript
在vue.js中使用JSZip实现在前端解压文件的方法
2018/09/05 Javascript
jQuery实现动画、消失、显现、渐出、渐入效果示例
2018/09/06 jQuery
Javascript中绑定click事件的四种方式介绍
2018/10/26 Javascript
vue-router启用history模式下的开发及非根目录部署方法
2018/12/23 Javascript
node中IO以及定时器优先级详解
2019/05/10 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
2021/02/20 Vue.js
[49:21]TNC vs VG 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第三场 8.20.mp4
2019/08/22 DOTA
Python里disconnect UDP套接字的方法
2015/04/23 Python
Python读取csv文件分隔符设置方法
2019/01/14 Python
python实现拼接图片
2020/03/23 Python
HTML+CSS3+JS 实现的下拉菜单
2020/11/25 HTML / CSS
英国版MAC彩妆品牌:Illamasqua
2018/04/18 全球购物
卡骆驰新加坡官网:Crocs新加坡
2018/06/12 全球购物
澳洲Chemist Direct药房中文网:澳洲大型线上直邮药房
2019/11/04 全球购物
P/Invoke是什么
2015/07/31 面试题
保密工作实施方案
2014/02/24 职场文书
田径运动会开幕式及主持词
2014/03/28 职场文书
结婚保证书范文
2014/04/29 职场文书
党员群众路线学习心得体会
2014/11/04 职场文书
2014年终个人工作总结
2014/11/07 职场文书
2015年精神文明建设工作总结
2015/04/21 职场文书
个人催款函范文
2015/06/23 职场文书
财务年终工作总结大全
2019/06/20 职场文书