BIT 类型
导学
当你需要存储纯二进制数据——比如 8 个开关的状态、权限标志位的组合、或者紧凑的布尔数组——用 TINYINT 浪费空间,用 SET 又不够底层。BIT 类型让你直接操作比特位,1 字节可以存 8 个布尔值,是存储二进制标志最高效的方式。
定义
BIT:位值类型,用于存储二进制数据(0 或 1 的序列)。可以指定长度 BIT(M),M 表示位数(1~64),存储空间按字节向上取整。
核心语法
CREATE TABLE 表名 (
列名 BIT(M) [NOT NULL] [DEFAULT b'0']
);
| 特性 | 说明 |
|---|---|
| 位数范围 | 1 ~ 64 |
| 存储空间 | (M + 7) / 8 字节,向上取整 |
| 字面量写法 | b'1010' 或 0b1010 |
| 显示方式 | 默认以二进制字符串显示,数值运算时转为整数 |
| 与整数转换 | BIT 可以参与整数运算,MySQL 会自动转换 |
演示数据准备
DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20),
dept VARCHAR(20),
score DECIMAL(5,2),
flags BIT(4) DEFAULT b'0000'
);
-- flags 位定义:第0位=是否在职, 第1位=是否远程, 第2位=是否管理员, 第3位=是否培训完成
INSERT INTO employees (emp_name, dept, score, flags) VALUES
('大翔', '技术部', 100, b'1111'), -- 在职+远程+管理员+培训完成
('白歌', '技术部', NULL, b'1001'); -- 在职+培训完成,非远程,非管理员
当前 employees 表中的完整数据如下:
| emp_id | emp_name | dept | score | flags |
|---|---|---|---|---|
| 1 | 大翔 | 技术部 | 100 | 1111 |
| 2 | 白歌 | 技术部 | NULL | 1001 |
SQL 示例
场景一:插入 BIT 值
当前数据状态:见上文 employees 表完整数据。
执行语句:
INSERT INTO employees (emp_name, dept, score, flags) VALUES ('孔蓝', '产品部', 88, b'1010');
操作后结果:
SELECT emp_name, flags FROM employees;
| emp_name | flags |
|---|---|
| 大翔 | 1111 |
| 白歌 | 1001 |
| 孔蓝 | 1010 |
结果解读:b'1010' 是二进制字面量,表示第 1 位和第 3 位为 1(从右数,从 0 开始)。孔蓝的 flags:第 0 位=0(不在职),第 1 位=1(远程),第 2 位=0(非管理员),第 3 位=1(培训完成)。
场景二:BIT 与整数的转换
当前数据状态:见上文 employees 表完整数据。
执行语句:
-- 将 BIT 转为整数显示
SELECT emp_name, flags, flags + 0 AS flags_int FROM employees;
操作后结果:
| emp_name | flags | flags_int |
|---|---|---|
| 大翔 | 1111 | 15 |
| 白歌 | 1001 | 9 |
| 孔蓝 | 1010 | 10 |
结果解读:flags + 0 将 BIT 强制转为整数。b'1111' = 15,b'1001' = 9,b'1010' = 10。这在需要数值比较或程序处理时非常有用。
场景三:按位查询(判断某个标志位是否置 1)
当前数据状态:见上文 employees 表完整数据。
执行语句:
-- 查询"在职"的人(第 0 位为 1)
SELECT emp_name, flags FROM employees WHERE flags & b'0001' = b'0001';
-- 等价于:WHERE flags & 1 = 1
-- 查询"是管理员"的人(第 2 位为 1)
SELECT emp_name, flags FROM employees WHERE flags & b'0100' = b'0100';
-- 等价于:WHERE flags & 4 = 4
操作后结果:
在职的人:
| emp_name | flags |
|---|---|
| 大翔 | 1111 |
| 白歌 | 1001 |
是管理员的人:
| emp_name | flags |
|---|---|
| 大翔 | 1111 |
结果解读:
flags & b'0001'用位与运算提取第 0 位。如果结果为b'0001'(即 1),说明第 0 位是 1flags & b'0100'提取第 2 位。b'0100'= 4,只有大翔的 flags(15)& 4 = 4,白歌的 9 & 4 = 0,孔蓝的 10 & 4 = 0
场景四:按位更新(置位和清零)
当前数据状态:见上文 employees 表完整数据。
执行语句:
-- 给白歌设置"远程"标志(第 1 位置 1)
UPDATE employees SET flags = flags | b'0010' WHERE emp_id = 2;
-- 等价于:flags = flags | 2
-- 取消大翔的"管理员"标志(第 2 位清 0)
UPDATE employees SET flags = flags & ~b'0100' WHERE emp_id = 1;
-- 等价于:flags = flags & ~4
操作后结果:
SELECT emp_name, flags FROM employees;
| emp_name | flags |
|---|---|
| 大翔 | 1011 |
| 白歌 | 1011 |
| 孔蓝 | 1010 |
结果解读:
- 白歌原
flags = b'1001'(9),| b'0010'(2)后变为b'1011'(11):第 1 位被置 1 - 大翔原
flags = b'1111'(15),& ~b'0100'(~4 = 11)后变为b'1011'(11):第 2 位被清 0
场景五:BIT 与 TINYINT 的对比
当前数据状态:创建对比表。
CREATE TABLE bit_demo (
id INT PRIMARY KEY,
flag_bit BIT(8), -- 1 字节存 8 个标志
flag_tiny TINYINT -- 1 字节存 1 个整数
);
INSERT INTO bit_demo VALUES (1, b'10101010', 170);
执行语句:
SELECT flag_bit, flag_bit + 0, flag_tiny FROM bit_demo;
操作后结果:
| flag_bit | flag_bit + 0 | flag_tiny |
|---|---|---|
| 10101010 | 170 | 170 |
结果解读:BIT(8) 和 TINYINT 都占 1 字节,但 BIT(8) 可以独立存储 8 个布尔标志,而 TINYINT 只能存一个 0~255 的整数。如果需要存储 8 个开关状态,BIT(8) 更语义化;如果只需要存一个 0~255 的数值,TINYINT 更直观。
常见误区
| 误区 | 正解 |
|---|---|
"BIT 只能存 1 位(0 或 1)" | 不是。BIT(M) 可以存 M 位,M 最大 64。 |
"BIT 显示的是十进制数字" | 默认显示二进制字符串(如 1010),用 + 0 可转为整数。 |
"BIT 不能参与数学运算" | 可以。MySQL 会自动将 BIT 转为整数参与运算。 |
"BIT(1) 和 TINYINT(1) 一样" | 不一样。BIT(1) 存 1 位(0/1),TINYINT(1) 存 1 字节(0~255),只是显示宽度为 1。 |
"BIT 适合存大量文本的二进制表示" | 不适合。BIT 最大 64 位,大量二进制数据用 BLOB 或 BINARY。 |
面试考点
Q:BIT 和 TINYINT 的区别?
BIT(M)存 M 位二进制数据,按位存储,适合标志位组合;TINYINT存 1 字节有符号整数(-128~127)或无符号(0~255),适合数值。BIT(8)和TINYINT都占 1 字节,但BIT(8)可以独立操作 8 个标志位。
Q:如何用 BIT 存储和查询多个布尔标志?
用
BIT(M)定义,每个标志对应一个位。置位用flags | (1 << n),清零用flags & ~(1 << n),查询用flags & (1 << n) > 0。n 是位的位置(从 0 开始)。
Q:BIT(1) 在程序中怎么映射?
BIT(1)在 MySQL 中显示为0或1(二进制字符串),程序读取时通常映射为布尔值false/true。注意:某些驱动可能返回字符串"0"/"1",需要转换。
Q:BIT 的最大长度是多少?占多少空间?
最大
BIT(64),占 8 字节。BIT(M)的存储空间为(M + 7) / 8字节,向上取整。例如BIT(1)~BIT(8)占 1 字节,BIT(9)~BIT(16)占 2 字节。
小结
BIT(M)用于存储 M 位二进制数据,1~64 位,存储空间按字节向上取整- 字面量用
b'1010'或0b1010表示,默认显示为二进制字符串 - 支持位运算(
&、|、~、^)进行标志位的查询、置位和清零 - 与整数可以互相转换(
+ 0转整数,直接赋值整数转 BIT) - 适合存储紧凑的布尔标志组合(如权限位、状态开关),大量二进制数据用
BLOB
下一章引子:BIT 适合存储二进制标志,但如果需要存储的是结构化的键值对数据——比如一个用户的配置项、一个商品的属性集——MySQL 5.7 引入的 JSON 类型是更现代的选择。