这个问题问到点子上了!_BIN 和 _BIN2 的区别,以及“码位”这个概念,是理解 SQL Server 排序规则底层机制的关键。
一、先讲“码位”是什么
词源角度
text
码位 = 码 + 位
| 汉字 | 词源 | 含义 |
|---|---|---|
| 码 | 来自英语 code(代码)的音译 | 一套编码系统中的编号 |
| 位 | 古汉语“位置” | 一个具体的位置/槽位 |
合并含义:
“在编码表(字符集)中,为每个字符分配的一个唯一编号位置”
直观理解
把字符集想象成一栋超级大的公寓楼:
| 概念 | 类比 |
|---|---|
| 字符集(如 Unicode) | 整栋公寓楼 |
| 码位 | 每个房间的门牌号(如 U+0041、U+4E2D) |
| 字符 | 住在房间里的“人”(如 A、中) |
Unicode 码位示例:
| 字符 | 码位(十六进制) | 码位(十进制) |
|---|---|---|
A | U+0041 | 65 |
a | U+0061 | 97 |
中 | U+4E2D | 20013 |
文 | U+6587 | 25991 |
“码位”就是给每个字符分配的、全球唯一的身份证号。
二、_BIN vs _BIN2 的核心区别
一句话总结
_BIN比较的是字符的“二进制存储形式”(可能有歧义),_BIN2比较的是字符的“码位”(无歧义)。
详细对比表
| 对比维度 | _BIN | _BIN2 |
|---|---|---|
| 全称 | Binary | Binary Code Point |
| 比较对象 | 字符在数据库中的实际二进制存储值 | 字符的Unicode 码位 |
| 引入版本 | SQL Server 7.0 (1998) | SQL Server 2005 (2005) |
| 算法 | 早期、不完整的二进制比较 | 严格、标准的码位比较 |
| 处理方式 | 直接比字节串 | 按 Unicode 标准比码位 |
| 大小写区分 | 严格区分(A ≠ a) | 严格区分(A ≠ a) |
| 兼容性 | 为了向后兼容保留 | 推荐使用 |
三、为什么会有 _BIN 和 _BIN2 两种?
历史原因

具体问题示例
在 _BIN 下可能出现的问题:
sql
-- 创建两个表,用不同的二进制排序规则CREATE TABLE test_bin (c nchar(1) COLLATE Chinese_PRC_BIN);CREATE TABLE test_bin2 (c nchar(1) COLLATE Chinese_PRC_BIN2);INSERT INTO test_bin VALUES (N'A'); -- 全角 AINSERT INTO test_bin VALUES (N'A'); -- 半角 AINSERT INTO test_bin2 VALUES (N'A'), (N'A');
在 _BIN 下:
比较的是存储的字节序列
全角
A和半角A的字节不同 → 被认为不同但某些字符对(如某些日语字符)在
_BIN下可能被错误地认为相等或不相等
在 _BIN2 下:
严格按 Unicode 码位比较
全角
A(U+FF21) 和半角A(U+0041) 码位不同 → 正确判定为不同所有比较都符合 Unicode 标准
四、更深入的技术区别
_BIN 的比较逻辑
text
字符 → 数据库存储编码(如 UCS-2/UTF-16)→ 直接比较字节
问题:
依赖数据库的存储实现
不同字符集/编码下结果可能不一致
不处理 Unicode 规范化问题
_BIN2 的比较逻辑
text
字符 → Unicode 码位 → 比较码位数值
优点:
独立于数据库存储方式
严格遵循 Unicode 标准
跨平台、跨版本结果一致
实际例子
| 场景 | _BIN 行为 | _BIN2 行为 |
|---|---|---|
比较 A 和 a | 不同(65 vs 97) | 不同(U+0041 vs U+0061) |
比较 é (U+00E9) 和 é (U+0065 + U+0301) | 可能相同或不同?取决于存储 | 不同(因为码位序列不同) |
| 比较日语全角/半角 | 不同 | 不同(码位不同) |
| 比较简体/繁体相同汉字 | 不同(码位不同) | 不同(码位不同) |
五、词源角度再深挖
_BIN 的词源
text
Binary (二进制) ← Latin binarius (由两部分组成的) ← Latin bini (成对的)
在 _BIN 中,"二进制" 指的是:
"把字符还原成计算机底层的 0 和 1,然后比较这些 0 和 1 组成的数字"
_BIN2 中 "2" 的含义
| 可能性 | 解释 |
|---|---|
| 版本号 | 第二个版本、改进版 |
| 不是平方 | 不是 BIN × BIN |
| 不是"too" | 不是 "binary too" |
准确含义: BIN 的第二版(Version 2)
类似命名:
Windows 2000 → Windows 2000
SQL Server 2005 → 版本 9.0
_BIN2→ 二进制排序规则第 2 代
六、实际建议
什么时候用哪个?
| 场景 | 推荐 | 原因 |
|---|---|---|
| 新项目 | _BIN2 | 标准化、准确、无 bug |
| 老系统维护 | _BIN | 保持兼容,不能随便改 |
| 跨平台应用 | _BIN2 | 行为一致 |
| 需要严格 Unicode 规范 | _BIN2 | 符合标准 |
验证方法
sql
-- 查看当前数据库的默认排序规则SELECT name, collation_name FROM sys.databases WHERE database_id = DB_ID();-- 查看某个表列的排序规则SELECT COLUMN_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'your_table';
七、总结表
| 概念 | 解释 | 词源 |
|---|---|---|
| 码位 | 字符在字符集中的唯一编号 | 码(code) + 位(position) |
_BIN | 比较字符的二进制存储值 | Binary(二进制) |
_BIN2 | 比较字符的 Unicode 码位 | Binary Code Point(二进制码位) |
一句话总结:
码位是字符的全球统一身份证号,
_BIN2就是拿着身份证号比大小;而_BIN是拿着身份证的复印件比(可能因为复印质量出问题)。
建议:新项目直接用 _BIN2,忘掉 _BIN 的存在