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 14 MySQL
详解Mysql和Oracle之间的误区
May 18 MySQL
Unity连接MySQL并读取表格数据的实现代码
Jun 20 MySQL
SQL实现LeetCode(178.分数排行)
Aug 04 MySQL
MySQL8.0的WITH查询详情
Aug 30 MySQL
MySQL数据库完全卸载的方法
Mar 03 MySQL
将MySQL的表数据全量导入clichhouse库中
Mar 21 MySQL
以MySQL5.7为例了解一下执行计划
Apr 13 MySQL
WINDOWS下安装mysql 8.x 的方法图文教程
Apr 19 MySQL
MySQL去除密码登录告警的方法
Apr 20 MySQL
Mysql开启外网访问
May 15 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
不用iconv库的gb2312与utf-8的互换函数
2006/10/09 PHP
div li的多行多列 无刷新分页示例代码
2013/10/16 PHP
C/S和B/S两种架构区别与优缺点分析
2014/10/23 PHP
PHP中使用匿名函数操作数据库的例子
2014/11/17 PHP
PHP中abstract(抽象)、final(最终)和static(静态)原理与用法详解
2020/06/05 PHP
用javascript实现的仿Flash广告图片轮换效果
2007/04/24 Javascript
javascript下高性能字符串连接StringBuffer类
2010/08/16 Javascript
jquery $.ajax相关用法分享
2012/03/16 Javascript
基于jQuery的input输入框下拉提示层(自动邮箱后缀名)
2012/06/14 Javascript
JS+flash实现chrome和ie浏览器下同时可以复制粘贴
2013/09/22 Javascript
xmlhttp缓存清除的2种解决方法
2013/12/13 Javascript
JavaScript html5 canvas绘制时钟效果
2016/03/01 Javascript
深入浅析Extjs中store分组功能的使用方法
2016/04/20 Javascript
浅析jQuery事件之on()方法绑定多个选择器,多个事件
2016/04/27 Javascript
JavaScript数组操作函数汇总
2016/08/05 Javascript
JS简单实现无缝滚动效果实例
2016/08/24 Javascript
vue2中filter()的实现代码
2017/07/09 Javascript
vue3.0 加载json的方法(非ajax)
2020/10/26 Javascript
Python中用startswith()函数判断字符串开头的教程
2015/04/07 Python
Python中encode()方法的使用简介
2015/05/18 Python
整理Python 常用string函数(收藏)
2016/05/30 Python
Python语言描述KNN算法与Kd树
2017/12/13 Python
python安装scipy的步骤解析
2019/09/28 Python
PyCharm汉化安装及永久激活详细教程(靠谱)
2020/01/16 Python
HTML5图片预览实例分享
2014/06/04 HTML / CSS
canvas之自定义头像功能实现代码示例
2017/09/29 HTML / CSS
Html5适配iphoneX刘海屏的简单实现
2019/04/09 HTML / CSS
英国顶级家庭折扣店:The Works
2017/09/06 全球购物
英语师范专业毕业生自荐信
2013/09/21 职场文书
社区庆八一活动方案
2014/02/02 职场文书
经营管理策划方案
2014/05/22 职场文书
春节晚会开场白
2015/05/29 职场文书
2015教师个人年度工作总结
2015/10/23 职场文书
Python Pandas pandas.read_sql函数实例用法
2021/06/21 Python
Ajax实现异步加载数据
2021/11/17 Javascript
win10输入法不见了只能打出字母怎么解决?
2022/08/05 数码科技