MySQL 使用 CAST 更新列值

MySQL update column value using CAST

我有简单的table(数据格式错误):

+========+
| weight |
+========+
| 100г   |
+--------+
| 200 г  |
+--------+
| 300гр  |
+--------+
| 400 гр |
+--------+
| 500г.  |
+--------+

当我这样做时,我可以对数据应用格式 select:

SELECT CONCAT((weight + 0), ' г') formatted FROM t;

+===========+
| formatted |
+===========+
| 100 г     |
+-----------+
| 200 г     |
+-----------+
| 300 г     |
+-----------+
| 400 г     |
+-----------+
| 500 г     |
+-----------+

现在我尝试使用以上格式更新数据:

UPDATE t SET weight = CONCAT((weight + 0), ' г');

但是出现错误:

Truncated incorrect DOUBLE value: '200 г'

Here the fiddle

您的 SELECT:

上出现相同的警告
mysql> SELECT CONCAT((weight + 0), ' г') formatted FROM t;
+-----------+
| formatted |
+-----------+
| 100 г     |
| 200 г     |
| 300 г     |
| 400 г     |
| 500 г     |
+-----------+
5 rows in set, 5 warnings (0.00 sec)

mysql> show warnings;
+---------+------+--------------------------------------------+
| Level   | Code | Message                                    |
+---------+------+--------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '100 г'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: '200 г'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: '300 г'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: '400 г'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: '500 г'  |
+---------+------+--------------------------------------------+

documentation on CAST() 对此进行了解释:

A string value containing non-numeric characters which must be truncated prior to conversion raises a warning, as shown here: ...

如果您只是对结果集 SELECT 执行 return,则警告不是致命的,但是 documentation on SQL modes 解释说:

Strict SQL mode applies to the following statements under conditions for which some value might be out of range or an invalid row is inserted into or deleted from a table:

UPDATE 是这些语句之一。如果你 SELECT 一个超出范围的值只会导致警告,但在严格模式下,你不能在插入或更新数据时使用这样一个狡猾的值。严格模式旨在防止您意外保存截断的数据。

那么如何解决你的问题呢?

一种方法是在当前会话中暂时禁用严格模式。

SET @sql_mode=@@sql_mode;
SET sql_mode='';
...do your UPDATE...
SET sql_mode=@sql_mode;

另一个解决方案是更明确地使用字符串的整数值,而不依赖于隐式 CAST。

示例:

SELECT CONCAT(REGEXP_SUBSTR(weight, '^[[:digit:]]*'), ' г') formatted FROM t;

+-----------+
| formatted |
+-----------+
| 100 г     |
| 200 г     |
| 300 г     |
| 400 г     |
| 500 г     |
+-----------+
5 rows in set (0.01 sec)

(注意没有警告)

REGEXP_SUBSTR() function 在 MySQL 8.0 中受支持。如果你使用旧版本的 MySQL,你必须用 SUBSTR() 做一些事情,否则就禁用严格的 sql_mode,就像我展示的那样。