乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

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_idemp_namedeptscoreflags
1大翔技术部1001111
2白歌技术部NULL1001

SQL 示例

场景一:插入 BIT 值

当前数据状态:见上文 employees 表完整数据。

执行语句:

INSERT INTO employees (emp_name, dept, score, flags) VALUES ('孔蓝', '产品部', 88, b'1010');

操作后结果:

SELECT emp_name, flags FROM employees;
emp_nameflags
大翔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_nameflagsflags_int
大翔111115
白歌10019
孔蓝101010

结果解读: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_nameflags
大翔1111
白歌1001

是管理员的人:

emp_nameflags
大翔1111

结果解读:

  • flags & b'0001' 用位与运算提取第 0 位。如果结果为 b'0001'(即 1),说明第 0 位是 1
  • flags & 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_nameflags
大翔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_bitflag_bit + 0flag_tiny
10101010170170

结果解读: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 类型是更现代的选择。

上一页
日期时间类型
下一页
ENUM 类型