• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    MySQL update set 和 and的区别

    问题描述

    最近接到一个奇怪的咨询,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+PostgreSQL批量插入更新insertOrUpdate
    • MySQL UPDATE 语句的非标准实现代码
    • mysql update case 更新字段值不固定的操作
    • Mysql update多表联合更新的方法小结
    • mysql事务select for update及数据的一致性处理讲解
    • MySQL UPDATE 语句一个“经典”的坑
    上一篇:MySQL查询学习之基础查询操作
    下一篇:MySQL 数据丢失排查案例
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    MySQL update set 和 and的区别 MySQL,update,set,和,and,的,区别,