如何重写 MySQL 更新语句以消除 "Truncated incorrect INTEGER value" 警告?

How do I rewrite my MySQL update statement to eliminate "Truncated incorrect INTEGER value" warnings?

我正在使用 MySQL 5.5.37。我想消除更新语句中的警告,如下所示...

update resource r 
    set grade_id = convert(substring_index(substring_index(
                   r.description, 'Grade ', -1), ' ', 1), unsigned integer) 
    where r.description like '% Grade%' 
      and CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(
                   r.description, 'Grade ', -1), ' ' ,1),UNSIGNED) > 0;

Query OK, 0 rows affected, 7 warnings (0.02 sec)
Rows matched: 1333  Changed: 0  Warnings: 7

mysql> show warnings;
+---------+------+--------------------------------------------------+
| Level   | Code | Message                                          |
+---------+------+--------------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
+---------+------+--------------------------------------------------+

我不明白的是,鉴于 none 正在更新的值与警告所抱怨的相匹配,我如何以不同的方式重写我的查询。下面是我的查询,我在其中列出了正在更新的不同值 ...

mysql> select distinct substring_index(substring_index(
              r.description, 'Grade ', -1), ' ', 1)
          from resource r
          where r.description like '% Grade%'
            and CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(
              r.description, 'Grade ',-1),' ',1),UNSIGNED) > 0;
+-----------------------------------------------------------------------+
| substring_index(substring_index(r.description, 'Grade ', -1), ' ', 1) |
+-----------------------------------------------------------------------+
| 7                                                                     |
| 8                                                                     |
| 11                                                                    |
| 9                                                                     |
| 12                                                                    |
| 10                                                                    |
| 6                                                                     |
+-----------------------------------------------------------------------+

如何重写我的更新语句,以便它更新相同的值而不尝试截断不正确的整数?

根据您的警告输出,在您的 resource.description 列中的某处您有 ''MyCo。有非数字数据被传递给 convert 函数,这是警告的来源。

我不知道您的原始数据是什么样的,但是如果您 运行 下面的查询,它应该会识别出任何 resource.description 格式不正确的行。

select distinct substring_index(substring_index(r.description, 'Grade ', -1), ' ', 1)
from resource r 
order by r.description

您也可以在查询中尝试 运行ning EXPLAIN。这可能会给你更多的洞察力。我不知道 MySQL 的内部结构,但尽管有 where 子句,但也许转换函数以某种方式查看所有行。

您收到警告是因为 WHERE 子句,而不是 SELECT 子句。由于无效(非数字)值被转换为 0 条件

CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(
          r.description, 'Grade ',-1),' ',1),UNSIGNED) > 0

重新调整 false。因此这些行不会出现在结果中。在 select 语句中删除该条件以查看哪些行导致警告:

select distinct 
    substring_index(substring_index(
        r.description, 'Grade ', -1), ' ', 1),
    CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(
        r.description, 'Grade ',-1),' ',1),UNSIGNED),
        r.description
from resource r
where r.description like '% Grade%';

示例:http://rextester.com/TVHN10678

由于我不知道你的数据,所以我无法帮助修复它。

据我所知,您收到的警告是由于 WHERE 子句条件

CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(r.description, 'Grade ',-1),' ',1),UNSIGNED) > 0

正如警告声明中明确提到的,由于 ''MyCo 值的整数值不正确而被截断。

| Level   | Code | Message                                          |
+---------+------+--------------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: ''            |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo'        |
| Warning | 1292 | Truncated incorrect INTEGER value: 'MyCo' 

这表明您在 resource table 的 description 列中没有任何特定的值模式 table。

喜欢下面

description
Foo Grade 100 Bar
Foo Grade 99 Grade 
Foo Grade 98 Grade MyCO

如上面第二行和第三行的代码所示,记录中有多个 Grade 字符串。 其中间接影响 SUBSTRING_INDEX(SUBSTRING_INDEX(r.description, 'Grade ',-1),' ',1), 行。 所以我的建议是请确保所有记录都正确插入。 如果所有记录都正确插入并检查它们是否包含多种类型的描述模式 column.If 包含多种模式,那么您必须使用 UNION 重写此查询。一个模式的单个查询和另一个模式的另一个查询。

然后尝试下面更新的查询。

   update resource r 
    set grade_id = convert(substring_index(substring_index(
                   r.description, 'Grade ', -1), ' ', 1), unsigned integer) 
    where r.description like '% Grade%' 
    and substring_index(substring_index(r.description, 'Grade ', -1), ' ', 1) REGEXP '[0-9]+';

希望这个解释对你有帮助。

您能否在转换之前使用 trim() 来删除任何可能已悄悄进入的空格?这些也是此警告的原因

您可以尝试使用正则表达式,例如:

where r.description like '% Grade%' and SUBSTRING_INDEX(SUBSTRING_INDEX( r.description, 'Grade ', -1), ' ' ,1) REGEXP '^[0-9]+$';

或者,如果您不害怕进入灰色区域:您也可以尝试完全不使用 CONVERT 的相同查询 - 令人惊讶的是它可能会起作用:

where r.description like '% Grade%' and SUBSTRING_INDEX(SUBSTRING_INDEX( r.description, 'Grade ', -1), ' ' ,1) > 0;

(我再次不确定这是否是记录在案的行为,因此 - 'gray area')。