【问题标题】:Why can you insert characters into a MySQL int field?为什么可以在 MySQL int 字段中插入字符?
【发布时间】:2010-02-15 03:11:39
【问题描述】:

我有一个 MySQL 数据库,它表现出我想更好地理解的行为。为什么我可以搜索插入 INT 字段的 CHAR 值?我有一个 INT 类型的字段,但它似乎能够记录字符值,这怎么可能?

我尝试通过使用 INT 和 VARCHAR 创建数据库来隔离问题。我将“TEST1”插入到 INT 值中,但仍然能够使用 ID 字符串值搜索行。将字符串插入ID值后的警告是

| Warning | 1366 | Incorrect integer value: 'TEST1' for column 'ID' at row 1 |

但我仍然能够搜索到该值。我想了解为什么会这样。

mysql> CREATE TABLE test1(ID int, DATA varchar(255));
Query OK, 0 rows affected (0.18 sec)

mysql> INSERT INTO test1(ID,DATA) VALUES('TEST1', 'TEST1');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> SELECT * FROM test1 WHERE ID = 'TEST1';
+------+-------+
| ID   | DATA  |
+------+-------+
|    0 | TEST1 |
+------+-------+
1 row in set, 1 warning (0.00 sec)

SELECT 之后的警告是

| Warning | 1366 | Incorrect integer value: 'TEST1' for column 'ID' at row 1 |

但结果还是正确的。

我希望上面的 SELECT 找到 0 个结果,但事实并非如此,为什么?

回答:

在下面 Asaph 的回答和 Pekka 的 cmets 的帮助下,现在答案似乎很明显了。

在 INSERT 期间,MySQL 未能将字符值插入 INT 字段,因此将其替换为 0。在 SELECT 期间发生了同样的事情,因此实际上我对 ID = 0 的任何字符值执行 SELECT搜索。

mysql> SELECT * FROM test1 WHERE ID = 'SOMETHING_OTHER_THAN_TEST1';
+------+-------+
| ID   | DATA  |
+------+-------+
|    0 | TEST1 |
+------+-------+
1 row in set, 1 warning (0.00 sec)

返回的结果与我最初的选择相同,因为它确实运行为

SELECT * FROM test1 WHERE ID = 0;

在后台。

无论如何,最佳实践似乎是在 MySQL 配置文件或 SQL 语句本身中使用 sql_mode = 'STRICT_ALL_TABLES'。

要为 MySQL 服务器上的所有 SQL 查询启用 STRICT_ALL_TABLES,您需要在 my.cnf 文件的 [mysqld] 标头下添加以下内容,该文件通常位于 /etc/my.cnf 中

[mysqld]
...
...
...
sql-mode=STRICT_ALL_TABLES

【问题讨论】:

  • 您是否注意到 MySQL 在执行查询时发出了1 warning...也许知道它是什么是件好事...?
  • 我用警告的结果更新了问题,但结果仍然正确,这是我想知道的。

标签: mysql


【解决方案1】:

您可以通过设置STRICT_ALL_TABLES 模式来防止插入无意义的值,该模式可以在my.cnf 中设置或即时设置:

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

mysql> CREATE TABLE test1(ID int, DATA varchar(255));
Query OK, 0 rows affected (0.42 sec)

mysql> INSERT INTO test1(ID,DATA) VALUES('TEST1', 'TEST1');
ERROR 1264 (22003): Out of range value adjusted for column 'ID' at row 1
mysql> SELECT * FROM test1 WHERE ID = 'TEST1';
Empty set (0.00 sec)

mysql> SELECT * FROM test1;
Empty set (0.00 sec)

【讨论】:

  • 谢谢,我将它添加到我的数据库配置中,因为这似乎是一种最佳实践,但我仍然想知道为什么 SELECT 实际上确实返回了正确的结果。
  • @Michael 我假设第一次转换(对于 ID)出错了,它回退到默认值 0
  • @Pekka - 我也这么认为,但 WHERE 子句专门寻找“TEST1”。如果该值默认为 0,它仍应返回 0 个结果。
  • @Michael mmm,那么失败的转换必须返回 0 - 应用于 int 字段的“TEST1”显然是这样做的。有趣!
  • @Michael Shnitzer 和@Pekka:当你运行SELECT * FROM test1 WHERE ID = 'TEST1'; 时,mysql 正在将'TEST1' 转换为一个int,因为它不能这样做,所以它以0 结束,这是默认值。如果您运行SELECT * FROM test1 WHERE ID = 'WHATEVERSTRING';,您将得到完全相同的结果。我刚刚确认了。自己试试吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多