建表时给 id、数量这类字段加不加 mysql unsigned,很多人纠结过。先说结论:确定永远不会有负数的字段可以加;会做减法的字段,加之前想清楚,相减出负数会直接报错。

unsigned 是什么意思

unsigned 是整数类型的无符号修饰,加上后不能存负数,正数范围翻一倍。以 int 为例:有符号范围是 -2147483648 到 2147483647,加 unsigned 后是 0 到 4294967295,存储空间不变,都是 4 个字节。其他整数类型同理:tinyint unsigned 是 0 到 255,做状态值很常用;bigint unsigned 上限则到 1.8 后面跟十八个 0 那个量级。

建表怎么写

CREATE TABLE t_order (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, pay_status TINYINT UNSIGNED DEFAULT 0, view_count INT UNSIGNED DEFAULT 0);

已有字段要改,用 ALTER TABLE t_order MODIFY view_count INT UNSIGNED DEFAULT 0 这种写法。反过来把 unsigned 改回有符号时,如果表里已有数据超出有符号范围,会报错,改之前先查一遍最大值。

最容易踩的坑:相减报错

两个 unsigned 字段相减,结果为负时,严格模式下 MySQL 直接报 BIGINT UNSIGNED value is out of range,整条语句失败。库存减销量、余额减支出这类场景尤其小心。常见的处理有三种:字段干脆用有符号;相减时用 CAST 转成有符号类型再算;或者把判断放到业务层,先查再减,不让负数出现。

别和显示宽度搞混

老项目里常见的 int(10) unsigned,括号里的 10 只是显示宽度,跟取值范围没关系,MySQL 8.0.17 起已经废弃了显示宽度,新表不用再写。AUTO_INCREMENT 字段习惯上加 unsigned,把完整范围留给自增值。

实际项目的一般做法:主键、计数、状态字段加 unsigned;金额、库存这类会被减的,老实用有符号或者 DECIMAL,省得哪天被一条相减报错打断上线。