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使用的编码究竟是什么,我也没有找到。

  • 相关阅读:
    Binary Search Tree Iterator 解答
    Invert Binary Tree 解答
    Min Stack 解答
    Trapping Raining Water 解答
    Candy 解答
    Jump Game II 解答
    Implement Hash Map Using Primitive Types
    Gas Station 解答
    Bucket Sort
    HashMap 专题
  • 原文地址:https://www.cnblogs.com/kuang17/p/6831389.html
Copyright © 2011-2022 走看看