PostgreSQL编码格式:客户端服务器、客户端、服务器端相关影响

关于字符编码这块,官网链接:

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     
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值