跳到主要内容

位串类型

位串类型用于保存由 0 和 1 组成的序列。PostgreSQL 提供固定长度 bit(n) 与可变长度 bit varying(n)(也写作 varbit)。它们适合位掩码、协议字段和紧凑的特征集合,不适合替代普通布尔列或二进制文件。

固定长度和可变长度​

CREATE TABLE flags (
object_id bigint PRIMARY KEY,
permissions bit(8) NOT NULL,
features bit varying(64)
);

INSERT INTO flags VALUES (1, B'10110010', B'11001');

bit(n) 必须始终有 n 位,短输入会补零(具体转换场景需以版本行为为准),过长输入会报错。bit varying(n) 最多 n 位,可以保存不同长度的位串;不写上限时表示不设显式长度上限。

位运算和访问​

SELECT B'1010' & B'1100' AS and_bits,
B'1010' | B'1100' AS or_bits,
B'1010' # B'1100' AS xor_bits,
~B'1010' AS not_bits;

SELECT get_bit(B'10110010', 0), set_bit(B'10110010', 2, 1);

位位置从 0 开始。&、|、#、~ 要求操作数长度兼容;长度不同的表达式应先显式转换或补齐,否则可能失败或产生不符合预期的结果。

字节与整数转换​

位串可以在适当场景下转换为整数或 bytea,但转换受位数、符号和字节序影响:

SELECT B'00001010'::integer;
SELECT encode(B'00001010'::bit(8)::bytea, 'hex');

协议解析时应明确字段的位序、端序和版本。把一段位串直接转换成整数并不自动表达协议的语义。

索引和建模​

如果总是按某一位过滤,可以建立表达式或生成列,并为生成列建索引:

ALTER TABLE flags
ADD COLUMN is_admin boolean
GENERATED ALWAYS AS (get_bit(permissions, 0) = 1) STORED;

CREATE INDEX flags_is_admin_idx ON flags (is_admin) WHERE is_admin;

对于少量稳定的开关,普通 boolean 列更可读、更容易约束和统计。位串适合需要批量位运算、字段数量较多且布局稳定的场景。

与 bytea、整数和数组的区别​

  • bit 表达“位的序列”,长度和位运算是核心。
  • bytea 表达“任意字节”,不关心每个位的业务含义。
  • 整数表达数值,比较和算术通常比位串更自然。
  • boolean[] 表达带元素边界的布尔集合,读取单项更直观。

常见误区​

  • 以为位串的每一位都等价于一个普通 boolean,却没有记录位编号和含义。
  • 忽略 0 起始下标、端序或协议版本。
  • 用 bit varying 存任意文件,导致编码、长度和传输语义混乱。
  • 把位掩码写成难以维护的魔法数字,未提供命名常量和约束。