mysql没有原生boolean类型,建表时写的boolean或bool会被服务端直接重写为tinyint(1),该类型本质是整数,取值范围为-128~127(有符号)或0~255(无符号),并非仅限0/1;括号中(1)仅影响显示宽度,不改变存储或语义;正确用法需配合check约束确保值域为{0,1},并注意jdbc连接参数tinyint1isbit=false以避免orm映射异常。

MySQL本身没有原生的BOOLEAN类型,所谓“布尔字段”只是语法糖,底层一律转成TINYINT(1)——这不是建议,而是事实。
为什么建表写BOOLEAN却看到TINYINT(1)?
你执行CREATE TABLE t (flag BOOLEAN)后,在DESCRIBE t或Navicat结构视图里看到TINYINT(1),不是工具出错,是MySQL服务端返回的真实类型。Server在解析时就把BOOLEAN重写为TINYINT(1),客户端只能照实展示。
-
BOOLEAN和BOOL是完全等价的别名,没有任何额外语义 - 哪怕你用
ALTER TABLE ... MODIFY flag BOOLEAN,查INFORMATION_SCHEMA.COLUMNS仍会显示TINYINT - 括号里的
(1)仅控制SELECT结果集的默认显示宽度(如ZEROFILL场景),不影响存储或取值范围
TINYINT(1)能存的不只是0和1
这是最容易踩的坑:它本质是整数,不是布尔。如果你没加约束,插入2、-5甚至127都合法。
- 有符号时取值范围是
-128到127;无符号才是0到255 - ORM(如MyBatis)默认把
TINYINT(1)映射为Boolean,但遇到非0/1值会抛SQLException或静默转为true(取决于JDBC驱动版本) - 正确做法是显式加约束:
is_active TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 CHECK (is_active IN (0, 1))
为什么不用ENUM('false','true')或CHAR(1)?
这些方案看似“更语义化”,但实际引入更多麻烦:
-
ENUM迁移困难,增删值需ALTER TABLE,且排序依赖枚举顺序而非逻辑真假 -
CHAR(1)浪费空间(至少1字节 vsTINYINT的1字节但可索引友好),且WHERE flag = '1'无法走索引(隐式类型转换) -
TINYINT(1)支持直接数值比较、范围查询、聚合函数(COUNT(flag)统计真值个数),而字符串类型做不到
真正要注意的从来不是“该不该用TINYINT(1)”,而是有没有配好约束、有没有在应用层统一处理非0/1值、以及JDBC连接串里是否加了tinyInt1isBit=false来禁用自动Boolean映射——后者在MyBatis里常导致resultType="map"和实体类映射行为不一致。











