zoukankan      html  css  js  c++  java
  • 由PostgreSQL的区域与字符集说起(转)

    转自:http://blog.chinaunix.net/uid-354915-id-3502551.html

    由PostgreSQL的区域与字符集说起

    一、PostgreSQL的区域
    区域属性有以下几个:
    LC_COLLATE:字符串排序顺序
    LC_CTYPE:字符分类(什么是字母?它是这个字母的等效大写?)
    LC_MESSAGES:信息的语言
    LC_MONETARY:货币金额的格式
    LC_NUMERIC:数字的格式
    LC_TIME:日期和时间的格式
    PostgreSQL 使用服务器操作系统提供的标准 ISO C 和 POSIX 区域机制。
    区域支持是在使用 initdb 创建一个数据库集群的时候自动初始化的。
    如果你的OS已经设置为你的数据库集群想要的区域,那么你就什么也不用干了。
    如果你想要你的系统表现得像没有区域支持一样,那么使用特殊的区域 C 或 POSIX 
    一些区域性质的值一旦运行了 initdb 之后,你就再也不能更改它们了。LC_COLLATE 和 LC_CTYPE 就是这样的。它们影响索引的排序顺序,因此它们必需保持固定,其它区域性质可以在服务器启动的时候根据需要通过配置postgresql.conf变量来改变,如果你在 postgresql.conf 里面删除了这些缺省值,那么服务器将会继承来自运行环境的设置。
    我们谈到从执行环境继承区域的时候,比如字符集,按照下面的顺序评估这些环境变量,直到找到一个已设置的:LC_ALL, LC_COLLATE, LANG 。如果这些环境变量一个都没有设置,那么区域缺省为 C 。一些信息区域化库也使用环境变量 LANGUAGE。
    请检查核实 PostgreSQL 确实使用了你认为它该用的区域设置。LC_COLLATE 和 LC_CTYPE 的设置都是在 initdb 时决定的,如果不重复 initdb 是不可能改变的。其它的区域设置包括 LC_MESSAGES 和 LC_MONETARY 都是由服务器的启动环境决定的,但是可以在运行时修改。你可以用 SHOW 命令检查数据库正在使用的区域设置。

    二、PostgreSQL的字符集
    缺省的字符集是在使用 initdb 初始化数据库集群的时候选择的。在你创建数据库的时候是可以覆盖这个缺省的。因此,你可以为多个数据库设置不同的字符集。
    虽然你可以给一个数据库声明你需要的任何编码,但选择一个与你选择的区域不一致的编码还是不妥的做法。LC_COLLATE 和 LC_CTYPE 设置暗示一个特定的编码,与区域相关的操作(比如排序)在不兼容的编码里很有可能产生错误的解析。
    一个安全使用多种编码的方法是在 initdb 的时候把区域设置为 C 或 POSIX ,这样就关闭了任何实际的区域敏感性。
    PostgreSQL 支持在服务器和前端之间的自动编码转换。
    假如无法进行特定的字符转换,比如,你选的服务器编码是 EUC_JP 而客户端是 LATIN1 ,那么有些日文字符不能转换成 LATIN1 。这时将报告错误。

    三、扩展:
    1、常见编码及转
    UTF8 = UNICODE8;
    UNICODE16是我们经常说的UNICODE;
    GBK即汉字内码扩展规范,GBK是ANSI的一种,用0x80~0xFF 范围的2个字节来表示1个字符,根据微软资料,GBK是对GB2312-80的扩展,也就是CP936字码表;
    windows英文版默认的应该是windows1252;
    windows中文版用的是GB2312/GBK(用dos命令chcp查看,936为简体中文);
    liunx很多默认编码都是utf-8,但是你可以通过命令设置成GB2312;
    网页编码,通常是跟编辑网页的编辑器有关,比如说你的编辑器设置为GB2312字符集,那么你的网页的编码就是GB2312的。如果你用英文的操作系统打开就会是乱码。不过现在的浏览器都支持字符集识别,它会帮你把GB2312编码的网页自动转换为unicode的网页,从而解决乱码的问题。
    如果你的文件编码是GBK,而你的系统环境是windows1252英文环境,那么这时候你打开文件就会是乱码的;
    解决方案有两种:
    (1)改变系统的语言为中文就可以解决乱码的问题;
    (2)将GBK编码的文件转换为unicode编码,unicode编码是万国码,一般的操作系统都支持,不存在打开后乱码的问题。
    每种编码都有自己的二进制编码集,平时经常遇到的问题是:
    (1)对字符进行了错误的编码解析,导致出现乱码;
    (2)字符在两个字符集中都存在,导致这部分字符变成“?”。
    2、数据库编程的编码问
    数据库编程设计的编码问题包括三个方面:
        数据库服务器编码;
        数据库客户端编码;
        本地环境编码。
    (1)数据库服务器字符编码:
    数据库服务器支持某种编码,是指数据库服务器能够从客户端接收、存储以及向客户端提供该种编码的字符,并能将该种编码的字符转换到其它编码。
    查看PostgreSQL数据库服务器端编码:
    postgres=# show server_encoding;
     server_encoding 
    -----------------
     UTF8
    postgres=# l
       名称    |  拥有者   | 字元编码 |                       Collate                       |                        Ctype                        |        TestDb1   | TestRole1 | UTF8     | Chinese (Simplified)_People's Republic of China.936 | Chinese (Simplified)_People's Republic of China.936 | 
     TestDb2   | postgres  | UTF8     | Chinese (Simplified)_People's Republic of China.936 | Chinese (Simplified)_People's Republic of China.936 | 
     postgres  | postgres  | UTF8     | Chinese (Simplified)_People's Republic of China.936 | Chinese (Simplified)_People's Republic of China.936 | 
     template0 | postgres  | UTF8     | Chinese (Simplified)_People's Republic of China.936 | Chinese (Simplified)_People's Republic of China.936 | 
    (2)数据库客户端字符编码:
     客户端工具支持某种编码,必须能够显示从数据库读取的该种编码的字符,也能通过本工具将该种编码的字符提交到给服务器端。       
     查看PostgreSQL客户端工具psql编码:
     postgres=# show client_encoding;
     GBK
     postgres=# encoding
     GBK
     指定Postgresql会话的客户端编码:
     postgres=# set client_encoding to 'utf8';
     SET
     postgres=# show client_encoding;
     client_encoding 
     -----------------
     UTF8
     (3)本地环境编码:
    如果使用dos的命令行界面,本地环境就是指dos命令行环境的编码,可以使用dos命令chcp查看dos环境编码:
    D:Program FilesPowerCmd>chcp
    活动代码页: 936
    ----936为简体中文,GBK;
    如果在使用某种编辑器,则本地环境编码取该编辑器的编码设置。

    四、实例
    虽然PG支持客户端和服务器端的编码自动转换,但是还需要遵从一个原则:本地环境的编码和客户端编码需一致。
    1、PostgreSQL的数据库postgres,服务器端字符编码为utf8,客户端工具psql字符编码为GBK,本地环境dos命令编辑器编码为GBK,此时:
    postgres=# show server_encoding;
     server_encoding 
    -----------------
     UTF8
    (1 行记录)
    postgres=# show client_encoding;
     client_encoding 
    -----------------
     GBK
    (1 行记录)
    postgres=# ! chcp
    活动代码页: 936
    postgres=# select * from "TestTb1";
      Column1                                                               
    -----------
     测试 
     11
    由于本地环境和客户端编码都是GBK,一致,没有问题;
    insert时,客户端接收本地环境输入的GBK字符(两者都为GBK),客户端传到服务器端时自动转换为UTF-8编码存储,没有问题;
    select时,服务器端传到客户端,UTF-8编码自动转换为GBK编码,在本地环境显示时,本地环境就是GBK编码,显示没有问题。

    2、PostgreSQL的数据库postgres,服务器端字符编码为utf8,客户端工具psql字符编码为utf8,本地环境dos命令编辑器编码为GBK,此时:
    postgres=# set client_encoding to 'utf8';
    SET
    postgres=# insert into test values('测试1');
    閿欒?:  鏃犳晥鐨?"UTF8" 缂栫爜瀛楄妭椤哄簭: 0xb2
    postgres=# select * from test;
          column1
    --------------------
     娴嬭瘯
    (1 行记录)                                                                                                        
    由于客户端和服务器的编码一致,故不进行转码,
    insert时,本地输入的GBK编码到客户端不自动转换,客户端把接收的字符作为utf编码传给服务器端不转换,GBK的编码作为UTF-8存储,故有问题。
    报错的信息为:ERROR:  invalid byte sequence for encoding "UTF8": 0xb2;
    select时,服务端的utf编码传给客户端不转换,客户端把utf编码传给本地环境不自动转换,utf8编码用gbk编码显示,故有问题。

    3、本地环境就是指此时使用的环境,起初我使用powercmd代替windows的cmd命令行工具,实现上面第1个实例是总是失败(乱码)。
    原因就是,此时本地环境编码是指powercmd的编码,而不是执行chcp命令得到的编码。
    而powercmd使用的编码究竟是什么,我也没有找到。

  • 相关阅读:
    Java生鲜电商平台-服务化后的互联网架构实战(针对生鲜电商小程序或者APP)
    你有一份新的C++书单,请注意查收!
    想了解大数据的鼻祖Hadoop技术栈,这里有一份优质书单推荐!
    程序员的健康问题终于有救了,有个资深程序员写了本《程序员健康指南》!
    《程序员如何优雅地挣零花钱》电子书免费开源!!!
    学习设计模式,你需要这样一份书单!
    《自拍教程36》段位三 Python面向对象类
    《自拍教程35》段位二 Python面向过程函数
    《自拍教程34》段位一 Python批处理脚本
    《自拍教程33》案例篇 内容介绍
  • 原文地址:https://www.cnblogs.com/kuang17/p/6831389.html
Copyright © 2011-2022 走看看