为什么以大写字母开头的字符排在以小写字母开头的字符之前?
Why are chars that start with capital letter sorted before those that start with lower letter?
我正在 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"=97。 65<97,意思是 "A"
在 "a"
之前存储。 OS 真的是这样工作的还是我还缺少其他东西?它在幕后是如何运作的?
中描述了 Sqlite3 如何选择比较函数来排序和比较字符串
基本上,如果您没有在表达式或相关列定义中使用 COLLATE
关键字显式声明一个,它会使用 BINARY
排序规则模式,就像 C memcmp()
函数用于比较值 - 它查看第一个不同字节的各个字节。
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
我正在 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"=97。 65<97,意思是 "A"
在 "a"
之前存储。 OS 真的是这样工作的还是我还缺少其他东西?它在幕后是如何运作的?
基本上,如果您没有在表达式或相关列定义中使用 COLLATE
关键字显式声明一个,它会使用 BINARY
排序规则模式,就像 C memcmp()
函数用于比较值 - 它查看第一个不同字节的各个字节。
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