[多是]比较中区分大小写的惟二数据库 | 数据库教程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 ..
复制代码

参考

相关文章
相关标签/搜索