关于字符编码这块,官网链接:
https://www.postgresql.org/docs/current/charset.html
刚刚写了几百字的东西因为断网,导致全没有了,重头再写,我就只想记录东西我自己看了:
1)客户端编码格式默认是从客户端的服务器编码获取,也就是LANG环境变量。
2)客户端编码和服务器编码如果一致,则插入的数据之间不经过转码,存入服务器。
3)客户端编码和服务器编码如果不一致,则插入的数据会传输到服务器端,并进行自动转码,存入数据库服务器。
4)如果服务器端传过来的数据,本地编码对应的字符集不支持中文,那么也就不能显示,即使编码转换是正确的。
越写越迷糊:
还是从客户端服务器编码,客户端编码,服务器编码来理一理:
客户端服务器编码:
[postgres@localhost ~]$ echo $LANG
en_US.UTF-8
客户端编码:
UTF8
服务器编码:
UTF8
当客户端的输入汉字时,是从客户端服务器编码集中获取的编码值,发现是UTF8,这时,客户端也是UTF8。服务器收到数据后,发现客户端和服务器编码一致都是UTF8,因此不做转换直接存储。查询也没有问题。
当客户端编码改为GBK时,客户端服务器编码还是UTF8。在输入汉字时,其实是UTF8的,而服务器收到数据时,发现客户端编码是GBK,就将UTF8的数据从GBK转为UTF8进行存储。可能会出错,就报错,如:
ERROR: character with byte sequence 0xad 0xe5 in encoding "GBK" has no equivalent in encoding "UTF8"
而有时候不出错,因为将实际上为UTF8的编码字符串转为了GBK的存储成功了,查询时,再将错误的UTF8编码转为了GBK(实际是原始的UTF8编码),显示时客户端服务器编码为UTF8,因此也能正常显示。
如果将客户端服务器、客户端都设为为GBK,服务器为UTF8。此时应该没有问题,因为在输入中文时,就是GBK编码,而客户端也是GBK,服务器就会将GBK编码转为UTF8,不会有错,存为UTF8字符串。查询时再做转换,在其他环境中查询也转为对应的编码显示。
因此,客户端服务器编码和客户端编码一定要统一,否则会出现输入的是客户端服务器编码,存储时却根据客户端编码往UTF8进行转换,导致出现错误或者乱码。
那么就有如下这种情况:
当我一开始使用UTF8插入数据,服务器端也是UTF8,查询显示都OK;然后修改客户端编码为GBK,插入数据,此时服务器自动会将GBK转换为UTF8,当在客户端查询时,再将UTF8转为GBK。
如果说都是从服务端的UTF8转为GBK,怎么会出现第一条是乱码,怎么解决?
不管怎么样,服务器都存放的是UTF8编码格式的数据,那么应该不存在乱码的问题啊?服务端统一将UTF8转为GBK,不能说第一条原本是UTF8没有发生转换过,因此往GBk转就失败。第二条也是从UTF8转为GBK的呢···,
除非!服务器端向客户端传输数据时根本没有转换:
当客户端和服务器端都为UTF8时,数据传输到服务器,直接存入为UTF8。
客户端变为GBK时,存入服务器也是GBK。
这样查询时,在GBK情况下,第一条返回为UTF8编码,根据GBK显示就是乱码。第二条本身就是GBK,因此不是乱码?
那么做一个实验:
开启两个客户端,一个是UTF8,一个是GBK,在两边各插入一条数据,看看两边的查询是否能正常显示。若能正常显示,说明在服务器端都转为了UTF8,如果两边各有一条显示为乱码,说明服务器端没转编码为UTF8.
psql中为UTF8,插入到UTF8的数据库中成功,改变为GBK后,插入失败:
postgres=# show client_encoding;
client_encoding
-----------------
UTF8
(1 row)
postgres=# show server_encoding;
server_encoding
-----------------
UTF8
(1 row)
postgres=# create table test(id int, info varchar(32), crt_time timestamp);
CREATE TABLE
postgres=# insert into test values(1, '中国-UTF8', now());
INSERT 0 1
postgres=# set client_encoding=GBK;
SET
postgres=# insert into test values(1, '中国-GBK', now());
ERROR: character with byte sequence 0xad 0xe5 in encoding "GBK" has no equivalent in encoding "UTF8"
psql为GBK时,插入失败:
[postgres@localhost ~]$ psql
psql (11.4)
Type "help" for help.
postgres=# \encoding
UTF8
postgres=# show server_encoding;
server_encoding
-----------------
UTF8
(1 row)
postgres=# show client_encoding;
client_encoding
-----------------
UTF8
(1 row)
postgres=# set client_encoding = GBK;
SET
postgres=# show client_encoding;
client_encoding
-----------------
GBK
(1 row)
postgres=# insert into test values(1, '中国-GBK', now());
ERROR: character with byte sequence 0xad 0xe5 in encoding "GBK" has no equivalent in encoding "UTF8"
postgres=#
下面是参考的资料:
PostgreSQL数据库支持多种字符集,在配置字符集时要分清楚服务器与客户端的字符集,字符集不一致尽管有时能够发生转换,但带来的问题也很头疼。语言环境的配置也很重要。
服务器字符集<来自文档>:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
Name Description Language Server? Bytes/Char Aliases
BIG5 Big Five Traditional Chinese No 1-2 WIN950, Windows950
EUC_CN Extended UNIX Code-CN Simplified Chinese Yes 1-3
EUC_JP Extended UNIX Code-JP Japanese Yes 1-3
EUC_JIS_2004 Extended UNIX Code-JP, JIS X 0213 Japanese Yes 1-3
EUC_KR Extended UNIX Code-KR Korean Yes 1-3
EUC_TW Extended UNIX Code-TW Traditional Chinese, Taiwanese Yes 1-3
GB18030 National Standard Chinese No 1-2
GBK Extended National Standard Simplified Chinese No 1-2 WIN936, Windows936
ISO_8859_5 ISO 8859-5, ECMA 113 Latin/Cyrillic Yes 1
ISO_8859_6 ISO 8859-6, ECMA 114 Latin/Arabic Yes 1
ISO_8859_7 ISO 8859-7, ECMA 118 Latin/Greek Yes 1
ISO_8859_8 ISO 8859-8, ECMA 121 Latin/Hebrew Yes 1
|