MySQL update set 和 and的区别

 更新时间:2021年05月08日 11:26:11   作者:王文安@DBA  
这篇文章主要介绍了MySQL update set 和 and的区别,帮助大家更好的理解和学习使用MySQL数据库,感兴趣的朋友可以了解下

问题描述

最近接到一个奇怪的咨询,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数据库高级用法之视图、事务、索引、自连接、用户管理实例分析

    这篇文章主要介绍了Mysql数据库高级用法之视图、事务、索引、自连接、用户管理,结合实例形式分析了MySQL数据库视图、事务、索引、自连接、用户管理常见用法及操作注意事项,需要的朋友可以参考下
    2019-11-11
  • MySql避免重复插入记录的几种方法

    MySql避免重复插入记录的几种方法

    本文章来给大家提供三种在mysql中避免重复插入记录方法,主要是讲到了ignore,Replace,ON DUPLICATE KEY UPDATE三种方法,有需要的朋友可以参考一下
    2013-08-08
  • MySQL使用xtrabackup进行备份还原操作

    MySQL使用xtrabackup进行备份还原操作

    这篇文章主要为大家详细介绍了MySQL如何使用xtrabackup进行备份还原操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Mysql数据库时间与系统时间不一致问题排查及解决

    Mysql数据库时间与系统时间不一致问题排查及解决

    最近忽然发现个问题,Mysql数据库时间与系统时间不一致,通过查找相关资料终于解决了,下面这篇文章主要给大家介绍了关于Mysql数据库时间与系统时间不一致问题排查及解决的相关资料,需要的朋友可以参考下
    2023-06-06
  • mysql查看binlog日志的实现方法

    mysql查看binlog日志的实现方法

    本文主要介绍了配置和查看MySQL 8.01的binlog日志,包括开启binlog日志、配置日志格式、查看日志位置和内容等,具有一定的参考价值,感兴趣的可以了解一下
    2024-11-11
  • Mysql数据库表中为什么有索引却没有提高查询速度

    Mysql数据库表中为什么有索引却没有提高查询速度

    你有没有想起过为什么明明再数据库中有索引,但是查询速度却并没有希望的那样快?本篇文章将带给你答案,跟小编一起看看吧
    2022-02-02
  • MySQL 数据备份与还原的示例代码

    MySQL 数据备份与还原的示例代码

    这篇文章主要介绍了MySQL 数据备份与还原的相关知识,本文通过示例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • MySQL生产环境CPU使用率过高的排查与解决方案

    MySQL生产环境CPU使用率过高的排查与解决方案

    在生产环境中,MySQL作为一个关键的数据库组件,其性能对整个系统的稳定性至关重要,有时候我们可能会遇到MySQL CPU使用率过高的问题,本文将详细介绍如何排查和解决MySQL CPU过高的问题,帮助您迅速恢复正常的数据库性能,需要的朋友可以参考下
    2024-03-03
  • MySQL8.0/8.x忘记密码更改root密码的实战步骤(亲测有效!)

    MySQL8.0/8.x忘记密码更改root密码的实战步骤(亲测有效!)

    忘记root密码的场景还是比较常见的,特别是自己搭的测试环境经过好久没用过时,很容易记不得当时设置的密码,下面这篇文章主要给大家介绍了关于MySQL8.0/8.x忘记密码更改root密码的实战步骤,亲测有效!需要的朋友可以参考下
    2023-04-04
  • MYSQL速度慢的问题 记录数据库语句

    MYSQL速度慢的问题 记录数据库语句

    Web程序慢,首先的一个检测对象就是数据库,写过几年程序的都知道。现在想追踪MySQL中那些拖累服务器性能的SQL语句,怎么办
    2012-06-06

最新评论