1

I have a question about MySQL comparing different data types. Let's say I have a following table:

CREATE TABLE `test`(  
  `value` VARCHAR(100)
);

Then I insert some data:

INSERT INTO test VALUES ('2XV4F2J');
INSERT INTO test VALUES ('123456');

Now if I run a simple select query:

SELECT * FROM test WHERE `value` = 2

I am aware of comparison of different types so in this case everything should be compared as 'floats' according to documentation. So as expected I get the result:

2XV4F2J

However when I try to run the update query

UPDATE test SET `value` = 'some other value' WHERE `value` = 2

I get the following error message:

Error Code: 1292
Truncated incorrect DOUBLE value: '2XV4F2J'

The thing I do not understand is why I am getting the error only when running UPDATE query. I would've expected to get the same error during SELECT as well.

4

1 回答 1

4

数据库的这种特殊行为由所谓的“SQL 模式”处理,很可能您的 MySQL 会话设置了“STRICT_TRANS_TABLES”,您可以通过发出:来验证这一点SELECT @@session.sql_mode;,请参阅下面的示例输出:

mysql> SELECT @@session.sql_mode;
+--------------------------------------------+
| @@session.sql_mode                         |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)

详细解释每种模式有点超出范围,但简而言之,在 STRICT_TRANS_TABLES 模式下,将回滚 DML 语句。这是为了确保数据库的完整性。这意味着您不能使用 UPDATES/INSERTS 破坏您的数据完整性,简而言之:“在 DML 的情况下,警告被视为错误”。在 SELECT 语句的情况下,不会有破坏数据库完整性的危险,因此在此模式下,如果您执行 SELECT,则会出现警告,但数据会转换为匹配值。这意味着由程序员来确保检索到的数据的有效性。

回到上面的示例,您可以关闭会话的严格模式,set sql_mode='';之后您的 UPDATE 将产生与示例中的 SELECT 相同的警告。

重要提示:请仔细阅读并理解 MySQL-Docs 的以下部分:服务器 SQL 模式,然后再敢于乱用服务器/会话的 SQL 模式。这可能会导致您的数据库将不一致,除非您和您的开发人员没有非常深入地了解他们在做什么。如上所述,完全由您来保证数据的一致性。我强烈建议您让 DBMS 完成这项工作!

请参阅下面使用您上面的示例的测试会话:

mysql> CREATE TABLE `test`(  
    ->   `value` VARCHAR(100)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO test VALUES ('2XV4F2J');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO test VALUES ('123456');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM test WHERE `value` = 2;
+---------+
| value   |
+---------+
| 2XV4F2J |
+---------+
1 row in set, 1 warning (0.00 sec)

mysql> UPDATE test SET `value` = 'some other value' WHERE `value` = 2;

ERROR 1292 (22007): Truncated incorrect DOUBLE value: '2XV4F2J'

现在禁用严格模式并进行更新:

mysql> set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE test SET `value` = 'some other value' WHERE `value` = 2;
Query OK, 1 row affected, 1 warning (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 1

mysql> show warnings;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '2XV4F2J' |
+---------+------+---------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from test;
+------------------+
| value            |
+------------------+
| some other value |
| 123456           |
+------------------+
2 rows in set (0.00 sec)
于 2013-07-26T08:03:57.147 回答