当前位置:   article > 正文

从 MySQL 执行 update 报错 ERROR 1292 说起

argument of and must be type boolean

157202a8d942e29df0356f05d93f000a.gif

作者 | JiekeXu

来源 |公众号 JiekeXu DBA之路(ID: JiekeXu_IT)

如需转载请联系授权 | (个人微信 ID:JiekeXu_DBA)

大家好,我是 JiekeXu,很高兴又和大家见面了,今天和大家一起来看看 MySQL 执行 update 报错 ERROR 1292 ,欢迎点击上方蓝字“JiekeXu DBA之路”关注我的公众号,标星或置顶,更多干货第一时间到达!

事情是这样的,上周五下班前通过自动化工具执行开发人员事先写好的 SQL 时,自动化工具执行失败了,于是手动去生产环境执行,就发生了错误 “ERROR 1292 (22007): Truncated incorrect DOUBLE value”,截断不正确的 DOUBLE 值,难道是数据类型长度不够,接下来我们查看一下表结构。

  1. mysql> update t_busi_cont set busi_contract_file='ba42cfdb-a1d0-4e5a-c' and busi_contract_file_ct=1
  2. -> where id='7823dcaade9145cdb8702d537';
  3. ERROR 1292 (22007): Truncated incorrect DOUBLE value: 'ba42cfdb-a1d0-4e5a-c'
  4. mysql> select busi_contract_file,busi_contract_file_ct from t_busi_cont where id='7823dcaade9145cdb8702d537';
  5. +------------------------------------------------+-----------------------+
  6. | busi_contract_file | busi_contract_file_ct |
  7. +------------------------------------------------+-----------------------+
  8. | undefined,ba42cfdb-a1d0-4e5a-c | 2 |
  9. +------------------------------------------------+-----------------------+

查看这个表结构,这两个字段类型也没毛病,字符型和整型,varchar(4000) 这也没啥问题,有可能是要下班了,着急下班,一时间竟没看出来是语法问题。。。。。。

  1. mysql> show create table t_busi_cont;
  2. CREATE TABLE `t_busi_cont` (
  3. `sequence_no` int(18) NOT NULL AUTO_INCREMENT COMMENT '顺序号',
  4. `id` varchar(36) COLLATE utf8mb4_bin NOT NULL COMMENT '合同明细编号',
  5. `busi_contract_file` varchar(4000) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '合同文件编号,逗号分隔',
  6. `busi_contract_file_ct` int(10) NOT NULL DEFAULT '0' COMMENT '合同文件张数'
  7. ……省去其他字段……
  8. PRIMARY KEY (`sequence_no`),
  9. UNIQUE KEY `u_t_ar_busi_contract_01` (`id`),
  10. );

然后使用客户端可视化工具、Xshell 命令行执行均出现一样的报错,没办法了,根据 SQL 逻辑先分开更新吧,分开按条件更新算是成功了,到这里还都没想到是语法的问题。。。。。。

  1. mysql> update t_busi_cont set busi_contract_file='ba42cfdb-a1d0-4e5a-c' where id='7823dcaade9145cdb8702d537';
  2. Query OK, 1 row affected (25.12 sec)
  3. Rows matched: 1 Changed: 1 Warnings: 0
  4. mysql> commit;
  5. Query OK, 0 rows affected (0.01 sec)
  6. mysql> update t_busi_cont set busi_contract_file_ct=1 where id='7823dcaade9145cdb8702d537';
  7. Query OK, 1 row affected (0.00 sec)
  8. Rows matched: 1 Changed: 1 Warnings: 0
  9. mysql> commit;
  10. Query OK, 0 rows affected (0.01 sec)

验证阶段,一时间没想明白,所以找了套测试环境,模拟了一下更新逻辑,如下所示,居然更新成功了。但是从下面的更新结果来看,只是将 id=1 的值更新成了 0 并没有将 c 列更新成 6 ,不符合预期。要想更新多列的值,则不能使用 AND,可以使用逗号分隔。虽然错误是因为子句语法问题,但 MySQL 错误描述也误导我是认为值有问题,触发此错误的原因之一是在更新表的多列时使用了 AND 子句,而没有使用逗号分隔多列

  1. Welcome to the MySQL monitor. Commands end with ; or \g.
  2. Your MySQL connection id is 48
  3. Server version: 8.0.28 MySQL Community Server - GPL
  4. Copyright (c) 2000, 2022, Oracle and/or its affiliates.
  5. Oracle is a registered trademark of Oracle Corporation and/or its
  6. affiliates. Other names may be trademarks of their respective
  7. owners.
  8. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  9. mysql> select * from t;
  10. +----+------+------+
  11. | id | c | d |
  12. +----+------+------+
  13. | 1 | 1 | 1 |
  14. | 2 | 2 | 2 |
  15. | 3 | 3 | 3 |
  16. | 4 | 4 | 4 |
  17. | 5 | 5 | 4 |
  18. +----+------+------+
  19. 5 rows in set (0.00 sec)
  20. mysql> update t set id=6 and c=6 where d=1; ----AND 连接
  21. Query OK, 1 row affected (0.06 sec)
  22. Rows matched: 1 Changed: 1 Warnings: 0
  23. mysql> select * from t;
  24. +----+------+------+
  25. | id | c | d |
  26. +----+------+------+
  27. | 0 | 1 | 1 |
  28. | 2 | 2 | 2 |
  29. | 3 | 3 | 3 |
  30. | 4 | 4 | 4 |
  31. | 5 | 5 | 4 |
  32. +----+------+------+
  33. 5 rows in set (0.00 sec)
  34. mysql> update t set id=6,c=6 where d=1; ----使用逗号分隔
  35. Query OK, 1 row affected (0.01 sec)
  36. Rows matched: 1 Changed: 1 Warnings: 0
  37. mysql> select * from t;
  38. +----+------+------+
  39. | id | c | d |
  40. +----+------+------+
  41. | 2 | 2 | 2 |
  42. | 3 | 3 | 3 |
  43. | 4 | 4 | 4 |
  44. | 5 | 5 | 4 |
  45. | 6 | 6 | 1 |
  46. +----+------+------+
  47. 5 rows in set (0.00 sec)

58c1e50786bf5494399bb1c5ec0f52e0.png

如上图的测试中,“update t set id=6 and c=6 where d=1;” 居然成功了,但是有一个问题,大家不知道想了没想,值为何会被更新为 0 了呢?可以先想一想,如果暂时要是想不到,可以接着看下图。

de32a41699d53f23e944fe1d4bf1f12e.png

看清楚了吗?上面图中“update t set id=‘6’ and c=‘6’ where d=1;”和“update t set id=‘6’ and c=‘1’ where d=1;” 都执行成功了,但是更新成功的值却不一样,前面为 1 后面 为 0 ,现在想到了吗?0、1、0、1 这不是布尔值么,在 MySQL 中,优化器将"set id=" 和 where 之间的子句当做一个值来处理,‘6’ and c=‘6’ 的结果被认为是 真,故更新为 id=1,‘6’ and c=‘1’ 的结果被认为是 假,故更新成 id=0 了(但是具体为啥会是这个结果呢,还是没搞明白,如果有大神看到可以不吝赐教),但是在生产环境中则出现了我下图中错误 数据类型不匹配 而报错,只是这报错提示有点让人摸不着头脑。

2e950d26bcdd049ca424556306789b94.png

在我的 Oracle 23c 的测试环境中,我去模拟了上面的操作,直接执行此 SQL 就报错了,ORA-00920 操作无效。

  1. Connected to:
  2. Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-Release
  3. Version 23.2.0.0.0
  4. SQL> CREATE TABLE JiekeXu.t1 (
  5. 2 id int NOT NULL,
  6. 3 c int DEFAULT NULL,
  7. 4 d int DEFAULT NULL,
  8. 5 PRIMARY KEY (id)
  9. 6 );
  10. Table created.
  11. SQL> insert into JiekeXu.t1 values(1,1,1),(2,2,2),(3,3,3); ----23c 新特性允许一次性插入多行值
  12. 3 rows created.
  13. SQL> commit;
  14. Commit complete.
  15. SQL> select * from JiekeXu.t1;
  16. ID C D
  17. ---------- ---------- ----------
  18. 1 1 1
  19. 2 2 2
  20. 3 3 3
  21. SQL> update JiekeXu.t1 set id=6 and c=6 where d=1;
  22. update JiekeXu.t1 set id=6 and c=6 where d=1
  23. *
  24. ERROR at line 1:
  25. ORA-00920: invalid relational operator
  26. SQL> update JiekeXu.t1 set id=6,c=6 where d=1;
1 row updated.

bf213a62032a4c99fa806b29d15574e5.png

下面我也测试了下在 PostgreSQL 14 版本中也是会直接报错,而且这个报错提示非常明显 ERROR:argument of AND must be type boolean, not type integer,AND 后面必须跟布尔类型而不是整型。

73955c42b9ff7ce69ff46a4570cdc2de.png

  1. $ psql
  2. psql (14.1)
  3. Type "help" for help.
  4. postgres=# \c jiekexu
  5. You are now connected to database "jiekexu" as user "postgres".
  6. jiekexu=# \dt
  7. List of relations
  8. Schema | Name | Type | Owner
  9. --------+---------------+-------+----------
  10. public | t | table | postgres
  11. public | t1 | table | postgres
  12. public | t_analyzeplan | table | postgres
  13. (3 rows)
  14. jiekexu=# CREATE TABLE test (
  15. jiekexu(# id int NOT NULL,
  16. jiekexu(# c int DEFAULT NULL,
  17. jiekexu(# d int DEFAULT NULL,
  18. jiekexu(# PRIMARY KEY (id)
  19. jiekexu(# );
  20. CREATE TABLE
  21. jiekexu=# insert into test values(1,1,1),(2,2,2),(3,3,3);
  22. INSERT 0 3
  23. jiekexu=#
  24. jiekexu=# select * from test;
  25. id | c | d
  26. ----+---+---
  27. 1 | 1 | 1
  28. 2 | 2 | 2
  29. 3 | 3 | 3
  30. (3 rows)
  31. jiekexu=# update test set id=6 and c=6 where d=1;
  32. ERROR: argument of AND must be type boolean, not type integer
  33. LINE 1: update test set id=6 and c=6 where d=1;
  34. ^
  35. jiekexu=# show server_version;
  36. server_version
  37. ----------------
  38. 14.1
  39. (1 row)

40a293685a83834f0aa563164e718773.png

全文完,希望可以帮到正在阅读的你,如果觉得此文对你有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~

欢迎关注我的公众号【JiekeXu DBA之路】,第一时间一起学习新知识!以下三个地址可以找到我,其他地址都属于盗版侵权爬取我的文章,而且代码格式、图片等错乱,不方便阅读,欢迎来我公众号或者墨天轮地址关注我,第一时间收获最新消息。

————————————————————————————
公众号:JiekeXu DBA之路
CSDN :https://blog.csdn.net/JiekeXu
墨天轮:https://www.modb.pro/u/4347
————————————————————————————

1212dbcc0b5d69618025af28c9833b74.gif

分享几个数据库备份脚本

Oracle 表碎片检查及整理方案

OGG|Oracle GoldenGate 基础2022 年公众号历史文章合集整理
 
 

Oracle 19c RAC 遇到的几个问题

OGG|Oracle 数据迁移后比对一致性

OGG|Oracle GoldenGate 微服务架构

Oracle 查询表空间使用率超慢问题一则

国产数据库|TiDB 5.4 单机快速安装初体验

Oracle ADG 备库停启维护流程及增量恢复

Linux 环境搭建 MySQL8.0.28 主从同步环境

bb5d1f0f8c0856d6055aeade49b23366.png

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/607081
推荐阅读
相关标签
  

闽ICP备14008679号