1. 什么是 UNSIGNED 类型
在 MySQL 中,我们可以为列定义 UNSIGNED 属性,它用于指定列中存储的是非负数。如果列的类型是 INT,则它可以存储的数字范围从 -2,147,483,648 到 2,147,483,647。但如果将该列定义为 UNSIGNED INT,则它可以存储的数字范围将是 0 到 4,294,967,295。
考虑到负数可能在某些情况下是不使用的,例如在存储年龄或天气情况时,UNSIGNED 属性是非常有用的。
2. 向 UNSIGNED 列插入负值
如果我们在使用 UNSIGNED 属性的列中插入负值,MySQL 数据库会发生以下情况:
2.1 报错
如果我们使用的是严格模式(STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES),则 MySQL 数据库将插入操作视为错误并返回错误消息,我们可以在该消息中看到以下内容:
mysql> CREATE TABLE test (
-> id INT UNSIGNED
-> );
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO test (id) VALUES (-1);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
该错误消息表明了由于插入的值超出了 UNSIGNED 字段的允许范围,因此操作失败。
2.2 插入结果
如果我们没有使用严格模式,则 MySQL 数据库将插入操作视为警告并对负值进行截断。例如:
mysql> INSERT INTO test (id) VALUES (-1);
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1264 | Out of range value for column 'id' at row 1 |
+---------+------+----------------------------------------+
mysql> SELECT * FROM test;
+------+
| id |
+------+
| 0 |
+------+
1 row in set (0.00 sec)
在上面的示例中,MySQL 数据库向 test 表的 id 列插入了负值。由于我们没有使用严格模式,因此插入操作不会产生错误而是产生了一个警告。MySQL 将负值转换为 0 并插入到 id 列。
考虑到截断的负值可能会导致数据不准确,我们强烈建议使用 UNSIGNED 属性的列应该在应用程序级别实施数据验证,以确保不会插入不合法的值。
3. 如何处理 UNSIGNED 列中的负值
如果我们在 UNSIGNED 列中需要存储负值而不是将其截断为 0,则可以将该列更改为 SIGNED INT 类型,或者如果我们需要使用值的范围,则可以将列更改为 BIGINT 类型。
在更改列类型时,我们应该注意数据会被截断,因此需要备份数据并在更改完成后验证其准确性。
4. 结论
如果我们在使用 UNSIGNED 属性的列中插入负值,MySQL 数据库会根据我们是否启用了严格模式进行错误处理或警告处理。为了保证数据的准确性,我们建议在应用程序层级实施数据验证,以确保不会插入不合法的值。
对于需要存储负值的情况,可以将 UNSIGNED 列更改为 SIGNED INT 或 BIGINT 类型。