oracle字符编码的理解

原文链接:http://blog.csdn.net/dbanote/article/details/9158367

一、查询服务端字符集
    select userenv(‘language‘) from dual; 

    USERENV(‘LANGUAGE‘)
    ----------------------------------------------------
    SIMPLIFIED CHINESE_CHINA.ZHS16GBK

二、 客户端NLS_LANG参数(即sqlplus的参数)该参数用于向Oracle指示客户端操作系统(sqlplus客户端)的字符集。
    select * from v$nls_parameters where parameter=‘NLS_CHARACTERSET‘;  

    PARAMETER                      VALUE
    ------------------------------ ------------------------------
    NLS_CHARACTERSET               ZHS16GBK

    设置客户端NLS_LANG
    C:\Users\85243>set nls_lang=Simplified Chinese_China.ZHS16GBK
    C:\Users\85243>set nls_lang=Simplified Chinese_China.AL32UTF8

三、客户端操作系统字符集
    C:\Users\85243>chcp
    活动代码页: 936
    936代表的是gbk编码 65001代表的是utf-8

有了以上3个基本概念之后,我来阐述一下Oracle字符集转换的基本原则:
  1.设置客户端的NLS_LANG为客户端操作系统的字符集
  2.如果数据库字符集等于NLS_LANG,数据库和客户端传输字符时不作任何转换
  3.如果它们俩不等,则需要在不同字符集间转换,只有客户端操作系统字符集是数据库字符集子集的基础上才能正确转换,否则会出现乱码。

几种常见情况分析
        1. 数据库字符集为Unicode(UTF-8编码)
        我们的数据库版本是10.2.0.4.0,数据库字符集是:
        SQL> select * from v$nls_parameters where parameter=‘NLS_CHARACTERSET‘;  

        PARAMETER                                VALUE
        ---------------------------------------- ------------------------------
        NLS_CHARACTERSET               AL32UTF8  

        2. 客户端操作系统字符集为代码页936(字符集为ZHS16GBK)
        可以使用chcp获得windows的代码页(code page)
        C:\Documents and Settings\a105024\Desktop>chcp
        Active code page: 936  

        3. 创建测试表
        SQL> create table test(id number,var varchar2(30));  

        Table created.  

        4. 插入数据
        这里在同一个操作系统启动两个session,session1的NLS_LANG设为和数据库字符集一样(即AL32UTF8):
        C:\Documents and Settings\a105024\Desktop>set nls_lang=Simplified Chinese_China.AL32UTF8
        连接数据库并插入一条数据:
        Session_1>insert into test values(1,‘中国‘);  

        1 row created.  

        Session_1>commit;  

        Commit complete.  

        session2的NLS_LANG设为和客户端操作系统一样(即ZHS16GBK):
        C:\Documents and Settings\a105024\Desktop>set nls_lang=Simplified Chinese_China.ZHS16GBK
        连接数据库并插入一条数据:
        Session_2>insert into test values(2,‘中国‘);  

        1 row created.  

        Session_2>commit;  

        Commit complete.  

        5. 执行查询
        在session 1上执行查询:
        Session_1>select * from test;  

                ID VAR
        ---------- ---------------------
                 1 中国
                 2 涓   浗
        在session 2上执行查询:
        Session_2>select * from test;  

                ID VAR
        ---------- --------------------
                 1 ???
                 2 中国  

上面例子看起来很诡异,session1和2都能正常显示自己插入的字符串,又都不能正常显示对方插入的字符串。为了弄清楚,我们首先得知道数据库里对这两个字符串是怎么存储的。我们可以使用dump函数获得字符在数据库的编码:

    SQL> select id,dump(var,1016) from test;
    ID DUMP(VAR,1016)
    -- ------------------------------------------------------------
     1 Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
     2 Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd
根据AL32UTF8的编码,“中国”两字的正确编码为(都为3个字节):
中--e4,b8,ad
国--e5,9b,bd
因此session 1插入的字符串在数据库中的编码是错误的,session 2正确。

场景1:session 1插入,session 1查询,在数据库中存储错误,但显示正确。

    插入过程:
    ”中国“两字在客户端操作系统字符集ZHS16GBK中的编码是”d6,d0,b9,fa",由于NLS_LANG和数据库字符集相同,数据库端对客户端传过来的字符编码不进行任何转换直接存入数据库,因此数据库中存储的编码也是“d6,d0,b9,fa”,
    读取过程:
    数据库端读取的编码是“d6,d0,b9,fa”,由于NLS_LANG和数据库字符集相同,客户端对数据库端传过来的字符编码不进行任何转换直接显示,编码”d6,d0,b9,fa“在客户端操作系统字符集ZHS16GBK对应的汉字为“中国”。
场景2:session 1插入,session 2查询,在数据库中存储错误,显示也错误。
    插入过程和场景1一样,这里就不再累述。
    读取过程:
    数据库端读取的编码是“d6,d0,b9,fa”,由于NLS_LANG和数据库字符集不同,客户端对数据库端传过来的字符编码进行转换,数据库端字符集AL32UTF8里编为“d6,d0,b9,fa”无法在客户端操作系统字符集ZHS16GBK里找到对应的编码,所以只好用?代替。

场景3:session 2插入,session 1查询,在数据库中存储正确,但显示错误。
    插入过程:
    ”中国“两字在客户端操作系统字符集ZHS16GBK中的编码是”d6,d0,b9,fa",由于NLS_LANG和数据库字符集不同,Oracle会进行字符编码转换,也就是将字符集ZHS16GBK里“中国”的编码“d6,d0,b9,fa"转换为字符集"AL32UTF8"里”中国“的编码”e4,b8,ad,e5,9b,bd“。
    读取过程:
    数据库端读取的编码是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和数据库字符集相同,客户端对数据库端传过来的字符编码不进行任何转换直接显示,编码”e4,b8,ad,e5,9b,bd“在客户端操作系统字符集ZHS16GBK对应的汉字为“涓   浗”(原本2个字符,现在变成了3个字符,因为ZHS16GBK的汉字以2个字节编码)。
场景4:session 2插入,session 2查询,在数据库中存储正确,显示也正确。
    插入过程和场景3类似。
    读取过程:
    数据库端读取的编码是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和数据库字符集不同,客户端对数据库端传过来的字符编码进行转换,数据库端字符集AL32UTF8里”中国“两字的编码”e4,b8,ad,e5,9b,bd“转换成客户端操作系统字符集ZHS16GBK里“中国”两字的编码“d6,d0,b9,fa",并正常显示。

原文:
http://blog.csdn.net/dbanote/article/details/9158367

时间: 2024-08-01 15:41:38

oracle字符编码的理解的相关文章

对字符编码的理解

1.含义 关于人类文明中的语言符号与计算机所认识的0和1之间的一个对应关系表.字符-------通过翻译----------计算机认识的数字.这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码.同一编码规范的不同版本间具有向下兼容性. 2.发展历史 (1)阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCIIASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256

Oracle字符编码与汉字存储长度的处理

执行如下语句,查看汉字在数据库中所占的字节: select vsize('汉') from dual; 一般情况下,得到的结果大部分为值:2 或 3 一般linux下安装oracle数据库,默认字符编码设为:AL32UTF8,每个汉字占3个字节 而windows平台下,默认字符编码设为:ZHS16GBK,每个汉字占2个字节 查看oracle服务端字符编码的SQL如下: select userenv('language') from dual; 数据迁移和前端字符长度校验,尤其要注意字符编码问题!

Python学习-字符编码的理解

Unicode编码和ASCII码两者都是机器能够理解的编码,你就是说出现一个码,计算机知道它对应哪种符号.因为这种编码形式将不同的字符全都和电平的高低电位联系在一起. Unicode,这种编码是全球通用的编码,就是说所有计算机都包含的编码.包含 utf-32(占4个字节),utf-16(占两个字节),utf-8(占1-4个字节),这三种形式. 也就是说utf-8,就是一种Unicode的编码. utf-16就是现在最常用的unicode版本, 不过在文件里存的还是utf-8,因为utf8省空间.

我对字符集和字符编码的理解

先定义两个概念. 字符集 字符集就是把字符和一串数字(码点)一一对应起来.GB2312,GBK,UNICODE,这些都是字符集. 字符编码 字符编码就是取得字符集中和字符对应的那串数字(字符编码)之后,基于取得的那串数字再生成另外一串数字.utf8,utf16,utf32这些都是字符编码. 字符集和字符编码的关系 我们可以把字符集看作一个函数,F(字符)=string1 我们也可以把字符编码看作另外一个函数,G(F(字符))=string2 string1即可以等于string2,也可以不等.

字符编码详解——彻底理解掌握编码知识,“乱码”不复存在

每一个程序员都不可避免的遇到字符编码的问题,特别是做Web开发的程序员,"乱码问题"一直是让人头疼的问题,也许您已经很少遇到"乱码"问题,然而,对解决乱码的方法的内在原理,您是否明白?本人作为一个程序员,在字符编码方面同样遇到不少问题,而且一直对各种编码懵懵懂懂.不清不楚:在工作中也曾经遇到一个很烦人的编码问题.这两天在网上收集了大量编码方面的资料,对字符编码算是理解的比较清楚了.下面把我认为比较重要的知识点记录下来,一方面方便以后复习:另一方面也希望给跟我一样懵懵

字符集和字符编码

1. 概述 现在的编程语言对字符串的处理一般封装比较好,所以平时编写代码,很少要自己考虑字符编码问题.以前学习xml时,由于xml的存储涉及到编码格式,查过一些资料,知道一些概念,GB2312.Unicode.Utf-8.Utf-16.UCS-2等,但这些概念之间什么关系,仍然一知半解.最近要做国际化,需要把不支持Unicode的程序升级为Unicode,借着这个机会,把其中的知识梳理了一遍,对字符编码的理解算更系统化了,在此总结一下. 2. 字符集和字符编码 首先明确两个概念,"字符集&quo

字符编码详解

每一个程序员都不可避免的遇到字符编码的问题,特别是做Web开发的程序员,“乱码问题”一直是让人头疼的问题,也许您已经很少遇到“乱码”问题,然而,对解决乱码的方法的内在原理,您是否明白?本人作为一个程序员,在字符编码方面同样遇到不少问题,而且一直对各种编码懵懵懂懂.不清不楚:在工作中也曾经遇到一个很烦人的编码问题.这两天在网上收集了大量编码方面的资料,对字符编码算是理解的比较清楚了.下面把我认为比较重要的知识点记录下来,一方面方便以后复习:另一方面也希望给跟我一样懵懵懂懂的人一个参考.不对或不妥之

字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)?

字符在内存中最终的表示形式是什么?是某种字符编码还是码位(Code Point)? 根据我的了解,编码中有三个核心概念:1. 字符集(Character Set),可以说是一个抽象概念,字符的合集2. 码位(Code Point),将抽象的字符集中每一个字符映射到一个整数3. 字符编码(Encoding),按照某种编码规则用二进制来表示一个字符 我对码位这个概念理解的不是很清楚,Code point中说: The notion of a code point is used for abstra

Python-3 文件和字符编码

文件 打开文件模式 ''' "r"只读模式(默认). w,只写模式,不可读,不存在则创建:存在则删除内容 a,追加模式,可读,不存在则创建:存在则只追加内容 x, 写模式,当文件系统上不存在,才可以写.也就是不允许覆盖已存在的文件内容 "+"表示可以同时读写某个文件: r+,可读写文件.可读:可写:可追加 w+,写读 a+,同a "U"表示在读取时,可以将 \r \n \r\n自动转换成\n(与r或r+ 模式同使用): rU r+U "