MySQL:WHERE子句中的整数到字符串类型比较

时间:2013-07-26 07:01:52

标签: mysql database

我有一个关于MySQL比较不同数据类型的问题。假设我有一张下表:

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

然后我插入一些数据:

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

现在,如果我运行一个简单的选择查询:

SELECT * FROM test WHERE `value` = 2

我知道不同类型的比较所以在这种情况下,根据文档,所有内容都应该作为'浮动'进行比较。所以我得到了结果:

2XV4F2J

但是当我尝试运行更新查询时

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

我收到以下错误消息:

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

我不明白的是为什么我只在运行UPDATE查询时才收到错误。我希望在SELECT期间也能得到同样的错误。

1 个答案:

答案 0 :(得分: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相同的警告。

重要事项:在您甚至敢于使用服务器/会话的SQL模式进行混乱之前,请仔细阅读并理解以下部分的MySQL-Docs:Server SQL Modes。这可能导致您的数据库不一致,除非您和您的开发人员不能非常详细地了解他们正在做什么。如上所述,它完全由您来保证数据的一致性。我强烈建议你让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)