[多是]比較中區分大小寫的惟二數據庫 | 數據庫教程9:PostgreSQL中對序規則、區分大小寫和字符集的支持,及修改查看Collate

這是我參與8月更文挑戰的第11天,活動詳情查看:8月更文挑戰html

字符集支持

字符集

對字符集的支持,能夠容許你使用多種字符集(也稱爲編碼)存儲文本,包括單字節字符集(如ISO 8859)和多字節字符集(如 EUC——Extended Unix Code、UTF-8和Mule internal codesql

字符集在 initdb 命令初始化PostgreSQL數據庫集羣是設置;也能夠在建立數據庫建立時指定。數據庫

關於PostgreSQL中的 LC_CTYPE 和 LC_COLLATE

  • LC_CTYPE —— character classification locale settings:本地設置的字符分類,即本地設置的字符類別,與字符集含義相似。markdown

  • LC_COLLATE —— string sort order locale settings:本地設置的字符串排序,即本地設置的排序規則。app

對於 CPOSIX locale,任何字符集都是容許的。其餘則不必定,好比Windows下,UTF-8編碼能夠在任何locale下使用。ide

locale 直接含義爲本地,在此處也能夠翻譯爲「語言環境」,或「本地語言環境」。函數

設置字符集

設置默認編碼

爲PostgreSQL集羣定義默認的字符集編碼:oop

initdb -E EUC_JP
複製代碼

上面設置的默認字符集爲:EUC_JP (Extended Unix Code for Japanese)。-E 是參數 --encoding 的縮寫。post

EUC_JP, EUC_CN, EUC_KR, EUC_TW.ui

爲數據庫指定編碼和排序規則

數據庫指定LC_COLLATE和LC_CTYPE後沒法修改。

爲一個數據庫指定另外一個編碼(改編碼須要與 初始化集羣時的locale兼容)

createdb -E EUC_KR -T template0 --lc-collate=ko_KR.euckr --lc-ctype=ko_KR.euckr korean
複製代碼

上面建立一個名爲 korean 的數據庫,該數據庫使用字符集 EUC_KR 和語言環境(locale) ko_KR

也可使用 SQL 命令實現:

CREATE DATABASE korean WITH ENCODING 'EUC_KR' LC_COLLATE='ko_KR.euckr' LC_CTYPE='ko_KR.euckr' TEMPLATE=template0;
複製代碼

上述命令指定複製 template0 數據庫。複製任何其餘數據庫時,沒法更改來自源數據庫的數據的編碼和區域設置,由於這可能會致使數據損壞。

查看數據庫的編碼

使用系統目錄 pg_database 能夠查看數據看編碼;也可使用 psql -l\l 命令查看

shop=# \l
                                                        數據庫列表
   名稱    |  擁有者  | 字元編碼(Encoding) |            校對規則(排序規則Collation)           |             Ctype              |       存取權限
-----------+----------+----------+--------------------------------+--------------------------------+-----------------------
 demo      | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 postgres  | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 shop      | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 template0 | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 | =c/postgres          +
           |          |          |                                |                                | postgres=CTc/postgres
 template1 | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 | =c/postgres          +
           |          |          |                                |                                | postgres=CTc/postgres
(5 行記錄)
複製代碼

可排序數據類型

概念上,可排序數據類型的每一個表達式都有一個排序規則。

通常常見的內置的可排序數據類型(collatable data type)有 text, varcharchar,用戶定義的基類型也能夠標記爲可整理...

若是表達式是列引用,則表達式的排序規則是列上已定義的排序規則。

若是表達式是常量,則排序規則是常量數據類型的默認排序規則。

更復雜表達式的排序規則源自其輸入的排序規則。

若是要進行排序操做或其餘須要排序規則的操做,則必需要有肯定的表達式的排序規則,表達式排序規則不肯定,排序將失敗。

好比Order By、或<比較操做符,或函數,會使用輸入表達式(輸入列)的排序規則。

獲取當前支持的collation

在全部平臺中,defaultCPOSIX 這三種排序規則都是可用的。

其餘的排序規則取決於操做系統的支持。

SQL標準的排序規則ucs_basic(用於UTF8編碼的collation)也是可用的。

要查看當前可用的排序能夠可使用系統目錄pg_collation。(在初始化數據庫系統時,initdb會使用在操做系統中找到的全部語言環境的排序規則填充系統目錄 pg_collat​​ion)

SELECT * FROM pg_collation;
複製代碼

psql 中,執行 \dOS+ 命令查看

shop=# SELECT * FROM pg_collation WHERE COLLNAME LIKE '%CN%';
  oid  |     collname     | collnamespace | collowner | collprovider | collisdeterministic | collencoding | collcollate | collctype  | collversion
-------+------------------+---------------+-----------+--------------+---------------------+--------------+-------------+------------+-------------
 12391 | bo-CN-x-icu      |            11 |        10 | i            | t                   |           -1 | bo_CN       | bo_CN      | 137.51.25
 12665 | ii-CN-x-icu      |            11 |        10 | i            | t                   |           -1 | ii_CN       | ii_CN      | 137.51.25
 12930 | ug-Arab-CN-x-icu |            11 |        10 | i            | t                   |           -1 | ug_Arab_CN  | ug_Arab_CN | 137.51.25
 12963 | zh-Hans-CN-x-icu |            11 |        10 | i            | t                   |           -1 | zh_Hans_CN  | zh_Hans_CN | 137.51.25
(4 行記錄)


shop=# SELECT * FROM pg_collation;
  oid  |        collname        | collnamespace | collowner | collprovider | collisdeterministic | collencoding | collcollate |  collctype  | collversion
-------+------------------------+---------------+-----------+--------------+---------------------+--------------+-------------+-------------+-------------
   100 | default                |            11 |        10 | d            | t                   |           -1 |             |             |
   950 | C                      |            11 |        10 | c            | t                   |           -1 | C           | C           |
   951 | POSIX                  |            11 |        10 | c            | t                   |           -1 | POSIX       | POSIX       |
 12326 | ucs_basic              |            11 |        10 | c            | t                   |            6 | C           | C           |
 ...
 ...
 ...
複製代碼

CREATE COLLATION語句能夠建立自定義的排序規則。

PostgreSQL的collation

建立一個存放ABab的數據表。後續操做基於此表演示。

CREATE TABLE OrderTest(
  letter char(1) NOT NULL
);
INSERT INTO OrderTest values('B'),('b'),('A'),('a');
複製代碼

PostgreSQL的排序規則彷佛有些不一樣,其默認的排序規則,在比較操做中是區分大小寫的,可是在排序操做中,是不區分大小寫的,至少默認不是按照字母編碼的值排序

具體查看下面的結果:

比較操做區分大小寫。

shop=# select * from OrderTest where letter ='A';
 letter
--------
 A
(1 行記錄)

shop=# select * from OrderTest where letter ='a';
 letter
--------
 a
(1 行記錄)
複製代碼

letter ='A'letter ='a'是兩個不一樣的結果。包括使用LIKE子句的比較,也是區分大小寫的。

排序操做默認不嚴格按照字符編碼值

shop=# select * from OrderTest order by letter;
 letter
--------
 a
 A
 b
 B
(4 行記錄)
複製代碼

如上所示,默認的排序結果中,a 和 A 被視爲相同並放在了一塊兒;b 和 B 被視爲相同並放在了一塊兒。

指定排序規則'C'或'POSIX',排序時嚴格區分碼值。

或者SQL標準的排序規則ucs_basic(用於UTF8編碼的collation),與'C'的行爲同樣。或者其餘嚴格區分碼值的排序規則

shop=# select * from OrderTest order by letter collate "ucs_basic";
 letter
--------
 A
 B
 a
 b
(4 行記錄)

shop=# select * from OrderTest order by letter collate "C";
 letter
--------
 A
 B
 a
 b
(4 行記錄)

shop=# select * from OrderTest order by letter collate "C" desc;
 letter
--------
 b
 a
 B
 A
(4 行記錄)
複製代碼

列排序規則

排序規則(collation)特性容許指定每列甚至每一個操做的數據的排序順序和字符分類行爲。

同時也能夠解除數據庫的 LC_COLLATELC_CTYPE 設置在建立後沒法修改的限制。

指定列的排序規則

以下,在建立表時指定列的排序規則:

CREATE TABLE test1 (
    a text COLLATE "zh-Hans-CN-x-icu",
    b text COLLATE "zh-Hant-TW-x-icu"
);
insert into test1 values('A','a'),('b','B');
複製代碼

此時,若是執行下面的比較查詢查詢將會發生錯誤:

shop=# SELECT a < b FROM test1;
錯誤:  沒法肯定字符串比較中使用哪一種排序規則
提示:  使用COLLATE子句來顯示設置排序規則.
複製代碼

這是由於a和b有隱式的排序規則的衝突。

在查詢中指定列或常量的排序規則 <column_name/constant_value> COLLATE "<collate_name>"

以下:

shop=# SELECT a < b COLLATE "zh-Hans-CN-x-icu" FROM test1;
 ?column?
----------
 f
 t
(2 行記錄)
複製代碼

查詢中的顯式使用排序規則

在某些狀況下,不一樣的查詢須要使用不一樣的排序規則來查詢同一列。

例如,一個查詢可能須要對列執行區分大小寫的比較,而另外一個查詢可能須要對同一列執行不區分大小寫的比較。這能夠經過在查詢內顯式指定排序規則來完成:

在查詢內使用COLLATE子句指定排序規則

在正常使用的SQL語句中的列名後面,指定COLLATE關鍵字及排序規則名,其餘部分和之前的SQL同樣,保持不變。

注意,COLLATE後的排序規則必選用雙引號包含,如COLLATE "ucs_basic"COLLATE "C",不然會報錯。MySQL/MariaDB、SQLServer中不須要雙引號包含。

<column_name/constant_value> COLLATE "<collate_name>"
複製代碼

好比查詢OrderTest表的按列排序。

-- 默認區分大小寫
shop=# select * from OrderTest where letter='a';
 letter
--------
 a
(1 行記錄)
複製代碼

彷佛,==PostgreSQL的UTF-8編碼下,未找到不區分大小寫的排序規則【也多是本身不會】==。

-- 指定查詢使用的排序規則
shop=# select * from OrderTest where letter COLLATE "C" ='a';
 letter
--------
 a
(1 行記錄)

shop=# select * from OrderTest where letter COLLATE "ucs_basic" ='a';
 letter
--------
 a
(1 行記錄)
複製代碼

PostgreSQL中建立不一樣排序規則的索引

PostgreSQL中能夠建立指定的排序規則的索引,即建立與列不一樣的排序規則的索引,一個列上建立多個不一樣索引。

詳細可查看相關官方文檔。

CREATE TABLE .. ( ..., field COLLATE <collation>, ... )
ALTER TABLE
CREATE INDEX .. ON ( field COLLATE <collation> )
CREATE INDEX .. ON ( (expr COLLATE <collation>) )
expr :: expr COLLATE <collation>
Possibly: CREATE COLLATE ..
複製代碼

參考

相關文章
相關標籤/搜索