W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
排序規(guī)則特性允許指定每一列甚至每一個(gè)操作的數(shù)據(jù)的排序順序和字符分類行為。這放松了數(shù)據(jù)庫的LC_COLLATE
和LC_CTYPE
設(shè)置自創(chuàng)建以后就不能更改這一限制。
在概念上,一種可排序數(shù)據(jù)類型的每一種表達(dá)式都有一個(gè)排序規(guī)則(內(nèi)建的可排序數(shù)據(jù)類型是text
、varchar
和char
。用戶定義的基礎(chǔ)類型也可以被標(biāo)記為可排序的,并且在一種可排序數(shù)據(jù)類型上的域也是可排序的)。如果該表達(dá)式是一個(gè)列引用,該表達(dá)式的排序規(guī)則就是列所定義的排序規(guī)則。如果該表達(dá)式是一個(gè)常量,排序規(guī)則就是該常量數(shù)據(jù)類型的默認(rèn)排序規(guī)則。更復(fù)雜表達(dá)式的排序規(guī)則根據(jù)其輸入的排序規(guī)則得來,如下所述:
一個(gè)表達(dá)式的排序規(guī)則可以是“默認(rèn)”排序規(guī)則,它表示數(shù)據(jù)庫的區(qū)域設(shè)置。一個(gè)表達(dá)式的排序規(guī)則也可能是不確定的。在這種情況下,排序操作和其他需要知道排序規(guī)則的操作會(huì)失敗。
當(dāng)數(shù)據(jù)庫系統(tǒng)必須要執(zhí)行一次排序或者字符分類時(shí),它使用輸入表達(dá)式的排序規(guī)則。這會(huì)在使用例如ORDER BY
子句以及函數(shù)或操作符調(diào)用(如<
)時(shí)發(fā)生。應(yīng)用于ORDER BY
子句的排序規(guī)則就是排序鍵的排序規(guī)則。應(yīng)用于函數(shù)或操作符調(diào)用的排序規(guī)則從它們的參數(shù)得來,具體如下文所述。除比較操作符之外,在大小寫字母之間轉(zhuǎn)換的函數(shù)會(huì)考慮排序規(guī)則,例如
lower
、upper
和initcap
。模式匹配操作符和to_char
及相關(guān)函數(shù)也會(huì)考慮排序規(guī)則。
對(duì)于一個(gè)函數(shù)或操作符調(diào)用,其排序規(guī)則通過檢查在執(zhí)行指定操作時(shí)參數(shù)的排序規(guī)則來獲得。如果該函數(shù)或操作符調(diào)用的結(jié)果是一種可排序的數(shù)據(jù)類型,萬一有外圍表達(dá)式要求函數(shù)或操作符表達(dá)式的排序規(guī)則,在解析時(shí)結(jié)果的排序規(guī)則也會(huì)被用作函數(shù)或操作符表達(dá)式的排序規(guī)則。
一個(gè)表達(dá)式的排序規(guī)則派生可以是顯式或隱式。該區(qū)別會(huì)影響多個(gè)不同的排序規(guī)則出現(xiàn)在同一個(gè)表達(dá)式中時(shí)如何組合它們。當(dāng)使用一個(gè)COLLATE
子句時(shí),將發(fā)生顯式排序規(guī)則派生。所有其他排序規(guī)則派生都是隱式的。當(dāng)多個(gè)排序規(guī)則需要被組合時(shí)(例如在一個(gè)函數(shù)調(diào)用中),將使用下面的規(guī)則:
如果任何一個(gè)輸入表達(dá)式具有一個(gè)顯式排序規(guī)則派生,則在輸入表達(dá)式之間的所有顯式派生的排序規(guī)則必須相同,否則將產(chǎn)生一個(gè)錯(cuò)誤。如果任何一個(gè)顯式派生的排序規(guī)則存在,它就是排序規(guī)則組合的結(jié)果。
否則,所有輸入表達(dá)式必須具有相同的隱式排序規(guī)則派生或默認(rèn)排序規(guī)則。如果任何一個(gè)非默認(rèn)排序規(guī)則存在,它就是排序規(guī)則組合的結(jié)果。否則,結(jié)果是默認(rèn)排序規(guī)則。
如果在輸入表達(dá)式之間存在沖突的非默認(rèn)隱式排序規(guī)則,則組合被認(rèn)為是具有不確定排序規(guī)則。這并非一種錯(cuò)誤情況,除非被調(diào)用的特定函數(shù)要求提供排序規(guī)則的知識(shí)。如果它確實(shí)這樣做,運(yùn)行時(shí)將發(fā)生一個(gè)錯(cuò)誤。
例如,考慮這個(gè)表定義:
CREATE TABLE test1 (
a text COLLATE "de_DE",
b text COLLATE "es_ES",
...
);
然后在
SELECT a < 'foo' FROM test1;
中,<
比較被根據(jù)de_DE
規(guī)則執(zhí)行,因?yàn)楸磉_(dá)式組合了一個(gè)隱式派生的排序規(guī)則和默認(rèn)排序規(guī)則。但是在
SELECT a < ('foo' COLLATE "fr_FR") FROM test1;
中,比較被使用fr_FR
規(guī)則執(zhí)行,因?yàn)轱@式排序規(guī)則派生重載了隱式排序規(guī)則。更進(jìn)一步,給定
SELECT a < b FROM test1;
解析器不能確定要應(yīng)用哪個(gè)排序規(guī)則,因?yàn)?code class="structfield">a列和b
列具有沖突的隱式排序規(guī)則。由于<
操作符不需要知道到底使用哪一個(gè)排序規(guī)則,這將會(huì)導(dǎo)致一個(gè)錯(cuò)誤。該錯(cuò)誤可以通過在一個(gè)輸入表達(dá)式上附加一個(gè)顯式排序規(guī)則說明符來解決,因此:
SELECT a < b COLLATE "de_DE" FROM test1;
或者等效的
SELECT a COLLATE "de_DE" < b FROM test1;
在另一方面,結(jié)構(gòu)相似的情況
SELECT a || b FROM test1;
不會(huì)導(dǎo)致一個(gè)錯(cuò)誤,因?yàn)?code class="literal">||操作符不關(guān)心排序規(guī)則:不管排序規(guī)則怎樣它的結(jié)果都相同。
如果一個(gè)函數(shù)或操作符發(fā)送一個(gè)具有可排序數(shù)據(jù)類型的結(jié)果,分配給該函數(shù)或操作符的組合輸入表達(dá)式的排序規(guī)則也被考慮應(yīng)用在函數(shù)或操作符的結(jié)果。因此,在
SELECT * FROM test1 ORDER BY a || 'foo';
中排序?qū)⒏鶕?jù)de_DE
規(guī)則完成。但這個(gè)查詢:
SELECT * FROM test1 ORDER BY a || b;
會(huì)導(dǎo)致一個(gè)錯(cuò)誤,因?yàn)榧词?code class="literal">||操作符不需要知道排序規(guī)則,但ORDER BY
子句需要。按照以前,沖突可以通過使用一個(gè)顯式排序規(guī)則說明符來解決:
SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR";
排序規(guī)則是SQL模式對(duì)象,它將SQL名稱映射到操作系統(tǒng)中安裝的庫提供的語言環(huán)境。 排序規(guī)則定義中有一個(gè)提供程序, 它指定哪個(gè)庫提供語言環(huán)境數(shù)據(jù)。一個(gè)標(biāo)準(zhǔn)的提供者名稱是libc
, 它使用操作系統(tǒng)C庫提供的語言環(huán)境。這些是操作系統(tǒng)提供的大多數(shù)工具使用的語言環(huán)境。 另一個(gè)提供者是icu
,它使用外部ICU
庫。 只有在構(gòu)建PostgreSQL時(shí)配置了對(duì)ICU的支持,才能使用ICU區(qū)域設(shè)置。
libc
提供的一個(gè)排序規(guī)則對(duì)象映射到LC_COLLATE
和LC_CTYPE
設(shè)置的組合, 如setlocale()
系統(tǒng)庫調(diào)用所接受的。 (正如其名字所說的,一個(gè)排序規(guī)則的主要目的是設(shè)置LC_COLLATE
, 它控制排序順序。但是在實(shí)際中
LC_CTYPE
設(shè)置與LC_COLLATE
不同是很少有必要的,因此通過一個(gè)概念來收集這些信息比為了設(shè)置每一個(gè)表達(dá)式的 LC_CTYPE
而創(chuàng)建另一種架構(gòu)要更加方便)。此外, 一個(gè)libc
排序規(guī)則是和一個(gè)字符集編碼(見第 23.3 節(jié))
綁定在一起的。相同的排序規(guī)則名字可能存在于不同的編碼中。
由icu
提供的排序規(guī)則對(duì)象映射到由ICU庫提供的指定整理器。 ICU不支持單獨(dú)的“collate”和“ctype”設(shè)置, 所以它們總是相同的。此外,ICU排序規(guī)則與編碼無關(guān), 因此在數(shù)據(jù)庫中總是只有一個(gè)給定名稱的ICU排序規(guī)則。
在所有的平臺(tái)上,名為default
、C
和POSIX
的排序規(guī)則都可用。附加的排序規(guī)則是否可用取決于操作系統(tǒng)的支持。default
排序規(guī)則選擇在數(shù)據(jù)庫創(chuàng)建時(shí)指定的LC_COLLATE
和LC_CTYPE
值。
C
和POSIX
排序規(guī)則都指定了“傳統(tǒng)的C”行為,在其中只有ASCII字母“A
”到“Z
”被視為字母,并且排序嚴(yán)格地按照字符編碼的字節(jié)值完成。
此外,SQL標(biāo)準(zhǔn)排序規(guī)則名稱ucs_basic
可用于編碼UTF8
。 它相當(dāng)于C
,并按Unicode代碼點(diǎn)排序。
如果操作系統(tǒng)支持在一個(gè)程序中使用多個(gè)區(qū)域(newlocale
和相關(guān)函數(shù)), 或者配置了ICU支持,那么在一個(gè)數(shù)據(jù)集簇被初始化時(shí),initdb
將以它在操作系統(tǒng)中能找到的所有區(qū)域?yàn)榛A(chǔ)在系統(tǒng)目錄pg_collation
中填充排序規(guī)則。
要檢查當(dāng)前可用的語言環(huán)境,請(qǐng)?jiān)?span id="mekokes" class="application">psql中使用查詢 SELECT * FROM pg_collation
或命令\dOS +
。
例如,操作系統(tǒng)可能會(huì)提供一個(gè)名為de_DE.utf8
的區(qū)域。initdb
則會(huì)創(chuàng)建一個(gè)用于編碼UTF8
的名為de_DE.utf8
的排序規(guī)則,在其中LC_COLLATE
和LC_CTYPE
都被設(shè)置為
de_DE.utf8
。它也會(huì)創(chuàng)建一個(gè)具有去掉名稱的.utf8
標(biāo)簽的排序規(guī)則。這樣你也可以使用名字de_DE
來使用該排序規(guī)則,這寫起來更簡(jiǎn)單并且使得名字更加獨(dú)立于編碼。不過要注意,最初的排序規(guī)則名稱的集合是平臺(tái)依賴的。
由libc
提供的默認(rèn)排序規(guī)則直接映射到操作系統(tǒng)中安裝的語言環(huán)境, 可以使用命令locale -a
列出。如果所需的libc
排序規(guī)則與LC_COLLATE
和LC_CTYPE
的值不同, 或者在數(shù)據(jù)庫系統(tǒng)初始化之后, 操作系統(tǒng)中安裝了新的語言環(huán)境,可以使用
CREATE COLLATION
命令創(chuàng)建新的排序規(guī)則。新的操作系統(tǒng)語言環(huán)境也可以使用 pg_import_system_collations()
函數(shù)集中導(dǎo)入。
在任何特定的數(shù)據(jù)庫中,只有使用數(shù)據(jù)庫編碼的排序規(guī)則是令人感興趣的。其他pg_collation
中的項(xiàng)會(huì)被忽略。因此,一個(gè)如de_DE
的被剝離的排序規(guī)則名在一個(gè)給定數(shù)據(jù)庫中可以被認(rèn)為是唯一的,即使它在全局上并不唯一。我們推薦使用被剝離的排序規(guī)則名,因?yàn)樵谀銢Q定要更改到另一個(gè)數(shù)據(jù)庫編碼時(shí)需要做的事情更少。但是要注意default
、
C
和POSIX
排序規(guī)則在使用時(shí)可以不考慮數(shù)據(jù)庫編碼。
PostgreSQL在碰到具有相同屬性的不同排序規(guī)則對(duì)象時(shí)會(huì)認(rèn)為它們是不兼容的。因此對(duì)于例子:
SELECT a COLLATE "C" < b COLLATE "POSIX" FROM test1;
將會(huì)得到一個(gè)錯(cuò)誤,即使C
和POSIX
排序規(guī)則具有相同的行為。因此,我們不推薦混合使用被剝離的和非被剝離的排序規(guī)則名。
對(duì)于ICU,枚舉所有可能的語言環(huán)境名稱并不明智。 ICU為語言環(huán)境使用特定的命名系統(tǒng),但命名語言環(huán)境的方法多于實(shí)際上不同的語言環(huán)境。 initdb
使用ICU API提取一組不同的語言環(huán)境以填充初始排序規(guī)則集合。 由ICU提供的排序規(guī)則是在SQL環(huán)境中創(chuàng)建的,名稱采用BCP 47語言標(biāo)記格式, 并附有一個(gè)“專用”擴(kuò)展名-x-icu
,
以將它們與libc語言環(huán)境區(qū)分開來。
以下是可能創(chuàng)建的一些排序規(guī)則的示例:
de-x-icu
德語排序規(guī)則,默認(rèn)變體
de-AT-x-icu
奧地利的德語排序規(guī)則,默認(rèn)變體
(也就是說de-DE-x-icu
或de-CH-x-icu
,但是這種寫法,相當(dāng)于 de-x-icu
。)
und-x-icu
(for “undefined”)ICU “root”排序規(guī)則。 使用它獲取合理的語言無關(guān)的排序順序
一些(不常用的)編碼不受ICU支持。當(dāng)數(shù)據(jù)庫編碼是其中之一時(shí), 忽略pg_collation
中的ICU排序規(guī)則項(xiàng)。 試圖使用其中一個(gè)將會(huì)拋出一個(gè)類似“collation "de-x-icu" for
encoding "WIN874" does not exist”的錯(cuò)誤。
如果標(biāo)準(zhǔn)和預(yù)定義的排序規(guī)則不夠用,用戶可以使用SQL命令 CREATE COLLATION創(chuàng)建自己的排序規(guī)則對(duì)象。
與所有預(yù)定于的對(duì)象一樣,標(biāo)準(zhǔn)和預(yù)定義的排序規(guī)則在模式 pg_catalog
中。用戶定義的排序規(guī)則應(yīng)該在用戶模式中創(chuàng)建。 這也確保它們由pg_dump
保存。
可以像這樣創(chuàng)建新的libc排序規(guī)則:
CREATE COLLATION german (provider = libc, locale = 'de_DE');
該命令中locale
子句可接受的確切值取決于操作系統(tǒng)。 在類Unix系統(tǒng)上,命令locale -a
將顯示一個(gè)列表。
由于預(yù)定義的libc排序規(guī)則已經(jīng)包含了數(shù)據(jù)庫實(shí)例初始化時(shí)在操作系統(tǒng)中定義的所有排序規(guī)則, 因此通常不需要手動(dòng)創(chuàng)建新排序規(guī)則。如果需要不同的命名系統(tǒng)(在這種情況下, 另請(qǐng)參閱第 23.2.2.3.3 節(jié)), 或者操作系統(tǒng)已經(jīng)升級(jí)以提供新的區(qū)域設(shè)置定義(在這種情況下, 另請(qǐng)參閱pg_import_system_collations()
), 可能需要手動(dòng)創(chuàng)建。
ICU允許自定義超出由initdb
預(yù)加載的基本語言+國(guó)家/地區(qū)集的排序規(guī)則。鼓勵(lì)用戶定義他們自己的排序規(guī)則對(duì)象, 利用這些條件來滿足他們排序行為的需求。請(qǐng)參閱 http://userguide.icu-project.org/locale和 http://userguide.icu-project.org/collation/api
獲取有關(guān)ICU區(qū)域設(shè)置命名的信息??山邮艿拿Q和屬性集取決于特定的ICU版本。
這里有些例子:
CREATE COLLATION "de-u-co-phonebk-x-icu" (provider = icu, locale = 'de-u-co-phonebk');
CREATE COLLATION "de-u-co-phonebk-x-icu" (provider = icu, locale = 'de@collation=phonebook');
德語排序規(guī)則和電話簿排序規(guī)則類型
第一個(gè)例子使用“語言標(biāo)簽”根據(jù) BCP 47選擇了ICU區(qū)域設(shè)置。 第二個(gè)示例使用傳統(tǒng)的ICU特定區(qū)域設(shè)置語法。第一種風(fēng)格是首選, 但它不受舊版ICU支持。
請(qǐng)注意,您可以在SQL環(huán)境中任意指定排序規(guī)則對(duì)象的名稱。 在這個(gè)例子中,我們遵循預(yù)定義排序規(guī)則使用的命名風(fēng)格, 而這種風(fēng)格又遵循BCP 47,但這對(duì)于用戶定義的排序規(guī)則不是必需的。
CREATE COLLATION "und-u-co-emoji-x-icu" (provider = icu, locale = 'und-u-co-emoji');
CREATE COLLATION "und-u-co-emoji-x-icu" (provider = icu, locale = '@collation=emoji');
根據(jù)Unicode技術(shù)標(biāo)準(zhǔn)#51,使用表情符號(hào)排序規(guī)則類型的根排序規(guī)則
觀察傳統(tǒng)ICU區(qū)域命名系統(tǒng)中的方式,根區(qū)域設(shè)置由空字符串選擇。
CREATE COLLATION latinlast (provider = icu, locale = 'en-u-kr-grek-latn');
CREATE COLLATION latinlast (provider = icu, locale = 'en@colReorder=grek-latn');
在拉丁字母之前對(duì)希臘字母進(jìn)行排序。(默認(rèn)為拉丁語在希臘語之前。)
CREATE COLLATION upperfirst (provider = icu, locale = 'en-u-kf-upper');
CREATE COLLATION upperfirst (provider = icu, locale = 'en@colCaseFirst=upper');
在小寫字母前面排列大寫字母。(默認(rèn)是小寫字母在前面。)
CREATE COLLATION special (provider = icu, locale = 'en-u-kf-upper-kr-grek-latn');
CREATE COLLATION special (provider = icu, locale = 'en@colCaseFirst=upper;colReorder=grek-latn');
結(jié)合上述兩個(gè)選項(xiàng)。
CREATE COLLATION numeric (provider = icu, locale = 'en-u-kn-true');
CREATE COLLATION numeric (provider = icu, locale = 'en@colNumeric=yes');
數(shù)字排序,按數(shù)字值排序數(shù)字序列,例如: A-21
< A-123
(也稱為自然排序)。
參閱Unicode 技術(shù)標(biāo)準(zhǔn) #35
和BCP 47獲取詳細(xì)信息。 可能的排序規(guī)則類型(co
子標(biāo)簽)列表可以在
CLDR 倉庫中找到。 區(qū)域設(shè)置瀏覽器
可以用于檢查一個(gè)特定區(qū)域設(shè)置定義的細(xì)節(jié)。使用k*
子標(biāo)簽的示例至少要求ICU版本54。
請(qǐng)注意,雖然此系統(tǒng)允許創(chuàng)建“忽略大小寫”或“忽略重音符”或類似(使用ks
鍵)的排序規(guī)則,但為了使這些排序規(guī)則真正以大小寫敏感或重音敏感方式工作,它們也需要在CREATE COLLATION
中定義為非
確定性的;見本文章中 第 23.2.2.4 節(jié)。否則,根據(jù)排序規(guī)則比較相等但按照字節(jié)不相等的任何字符串將根據(jù)其字節(jié)值進(jìn)行排序。
根據(jù)設(shè)計(jì),ICU幾乎可以接受任何字符串作為區(qū)域名稱, 并使用其文檔中描述的后備程序?qū)⑵渑c最接近的區(qū)域設(shè)置相匹配。因此, 如果使用給定ICU安裝實(shí)際上不支持的功能組合排序規(guī)范,則不會(huì)有直接反饋。 因此建議創(chuàng)建應(yīng)用程序級(jí)別的測(cè)試用例,以檢查排序規(guī)則定義是否滿足需求。
也可以使用命令CREATE COLLATION 從現(xiàn)有的排序規(guī)則創(chuàng)建新的排序規(guī)則, 這對(duì)于能夠在應(yīng)用程序中使用與操作系統(tǒng)無關(guān)的排序規(guī)則名稱、 創(chuàng)建兼容性名稱或以更易讀的名稱使用ICU提供的排序規(guī)則很有幫助。例如:
CREATE COLLATION german FROM "de_DE";
CREATE COLLATION french FROM "fr-x-icu";
排序規(guī)則要么是確定性的,要么是非確定性的。 確定性排序規(guī)則使用確定性比較方法,也就意味著字符串要認(rèn)為是相等的話,只有在它們是由相同的字節(jié)順序組成的時(shí)候。 非確定性比較可以確定字符串相等,即使它們由不同字節(jié)組成。 典型的情形包括大小寫敏感比較、重音敏感比較和不同Unicode規(guī)范形式的字符串的比較。 非敏感比較的實(shí)際是由排序規(guī)則提供程序來實(shí)現(xiàn)的;確定性標(biāo)志僅確定使用按字節(jié)比較時(shí)關(guān)系是否要斷開。 也可參見Unicode技術(shù)標(biāo)準(zhǔn)10獲得更多術(shù)語信息。
創(chuàng)建非確定性排序規(guī)則時(shí),指定屬性deterministic = false
以CREATE COLLATION
,例如:
CREATE COLLATION ndcoll (provider = icu, locale = 'und', deterministic = false);
該例子以非確定性方式使用標(biāo)準(zhǔn)的Unicode排序規(guī)則。特別地,這將允許不同規(guī)范形式的字符串能正確地比較。更有趣的例子是使用上述的ICU定制化功能。例如:
CREATE COLLATION case_insensitive (provider = icu, locale = 'und-u-ks-level2', deterministic = false);
CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-true', deterministic = false);
所有標(biāo)準(zhǔn)和預(yù)定義的排序規(guī)則是確定性的,所有用戶自定義的排序規(guī)則缺省是確定性的。 盡管非確定性規(guī)則提供了更“正確”的行為,尤其是考慮到Unicode和其許多特殊情況的全部能力時(shí),也有一些缺點(diǎn)。 首先,使用它們會(huì)導(dǎo)致性能下降。特別請(qǐng)注意,B-tree不能將重復(fù)數(shù)據(jù)消除與使用非確定性排序的索引一起使用。 此外,用非確定性規(guī)則排序時(shí)某些操作就不可能做,例如模式匹配。因此,僅在特別需要它們的情況下才使用。
要處理不同 Unicode 規(guī)范化格式中的文本,還有一個(gè)選項(xiàng),使用函數(shù)/表達(dá)式normalize
和 is normalized
預(yù)處理或檢查字符串,而不是使用非確定性排序規(guī)則。每種方法都有不同的權(quán)衡。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: