首页 > 解决方案 > 为什么以大写字母开头的字符排在以小写字母开头的字符之前?

问题描述

我在SQL中做一些基本的排序,我很久以前就学会了:以大写字母开头的名称在以小写字母开头的名称之前排序。例子:

sqlite> create table letters (letter text);
sqlite> insert into letters values ('A');
sqlite> insert into letters values ('C');
sqlite> insert into letters values ('b');
sqlite> insert into letters values ('d');

sqlite> select * from letters order by letter asc;

输出:

A
C
b
d

在这种情况下,我们需要输入:sqlite> select * from letters order by letter collate nocase asc;,这将给出预期的输出:

A
b
C
d

但我的问题是为什么它是这样排序的?我试图找到答案,但我失败了。我唯一的猜测是 ASCII 为"A"=65,而"a"=9765<97,意思是"A"在之前存储"a"。操作系统真的以这种方式工作还是我还缺少其他东西?它是如何在幕后工作的?

标签: sqlsqlitesortingsql-order-byascii

解决方案


数据类型文档中描述了 Sqlite3 如何选择比较函数来排序和比较字符串。

基本上,如果您没有COLLATE在表达式或相关列定义中使用关键字显式声明一个,它会使用BINARY排序规则模式,就像 Cmemcmp()函数用于比较值一样 - 它查看第一个字节的单个字节不同。

Sqlite 使用 Unicode 存储文本值(使用 UTF-8 或 UTF-16,请参阅PRAGMA encoding)。Unicode 的前 127 个代码点与 ASCII 相同,因此具有较低值的大写英文字母将在排序规则中排在小写字母之前BINARY

烦人的是,这意味着可以根据底层编码以不同的方式对相同的数据进行排序:

$ sqlite3 test1.db
sqlite> PRAGMA encoding='UTF-16LE';
sqlite> CREATE TABLE test(word TEXT);
sqlite> INSERT INTO test VALUES ('A'), ('a'), ('B'), ('b'), (char(0x1F355));
sqlite> SELECT word, hex(word), unicode(word) FROM test ORDER BY word;
word  hex(word)  unicode(word)
----  ---------  -------------
     3CD855DF   127829       
A     4100       65           
B     4200       66           
a     6100       97           
b     6200       98
sqlite> .quit
$ sqlite3 test2.db
sqlite> PRAGMA encoding='UTF-16BE';
sqlite> CREATE TABLE test(word TEXT);
sqlite> INSERT INTO test VALUES ('A'), ('a'), ('B'), ('b'), (char(0x1F355));
sqlite> SELECT word, hex(word), unicode(word) FROM test ORDER BY word;
word  hex(word)  unicode(word)
----  ---------  -------------
A     0041       65           
B     0042       66           
a     0061       97           
b     0062       98           
     D83CDF55   127829
sqlite> .quit
$ sqlite3 test3.db
sqlite> PRAGMA encoding='UTF-8';
sqlite> CREATE TABLE test(word TEXT);
sqlite> INSERT INTO test VALUES ('A'), ('a'), ('B'), ('b'), (char(0x1F355));
sqlite> SELECT word, hex(word), unicode(word) FROM test ORDER BY word;
word  hex(word)  unicode(word)
----  ---------  -------------
A     41         65           
B     42         66           
a     61         97           
b     62         98           
     F09F8D95   127829

推荐阅读