Oracle 字符集问题

1 简介 ORACLE数据库字符集,即Oracle全球化支持(Globalization Support),或即国家语言支持(NLS)其做用是用本国语言和格式来存储、处理和检索数据。利用全球化支持,ORACLE为用户提供本身熟悉的数据库母语环境,诸如日期格式、数字格式和存储序列等。Oracle能够支持多种语言及字符集,其中oracle8i支持48种语言、76个国家地域、229种字符集,而oracle9i则支持57种语言、88个国家地域、235种字符集。因为oracle字符集种类多,且在存储、检索、迁移Oracle数据时多个环节与字符集的设置密切相关,所以在实际的应用中,数据库开发和管理人员常常会遇到有关oracle字符集方面的问题。本文经过如下几个方面阐述,对oracle字符集作简要分析 2 字符集基本知识 2.1字符集 实质就是按照必定的字符编码方案,对一组特定的符号,分别赋予不一样数值编码的集合,是各个字符的一种二进制表示(用位和字节表示)。目前有多种不一样的字符集,每种字符集能表示不一样的字符。Oracle数据库最先支持的编码方案是US7ASCII。 Oracle的字符集命名遵循如下命名规则: 即: <语言><比特位数><编码> 好比: ZHS16GBK表示采用GBK编码格式、16位(两个字节)简体中文字符集 2.2字符编码方案 2.2.1单字节编码 (1)单字节7位字符集,能够定义128个字符,最经常使用的字符集为US7ASCII (2)单字节8位字符集,能够定义256个字符,适合于欧洲大部分国家 例如:WE8ISO8859P1(西欧、8位、ISO标准8859P1编码) 2.2.2 多字节编码 (1)变长多字节编码 某些字符用一个字节表示,其它字符用两个或多个字符表示,变长多字节编码经常使用于对亚洲语言的支持, 例如日语、汉语、印地语等 例如:AL32UTF8(其中AL表明ALL,指适用于全部语言)、zhs16cgb231280 (2)定长多字节编码 每个字符都使用固定长度字节的编码方案,目前oracle惟一支持的定长多字节编码是AF16UTF16,也是仅用于国家字符集 2.2.3 Unicode编码 Unicode是一个涵盖了目前全世界使用的全部已知字符的单一编码方案,也就是说Unicode为每个字符提供惟一的编码。UTF-16是Unicode的16位编码方式,是一种定长多字节编码,用2个字节表示一个Unicode字符,AF16UTF16是UTF-16编码字符集。 UTF-8是Unicode的8位编码方式,是一种变长多字节编码,这种编码能够用一、二、3个字节表示一个Unicode字符,AL32UTF8,UTF八、UTFE是UTF-8编码字符集 2.3 字符集超级 当一种字符集(字符集A)的编码数值包含全部另外一种字符集(字符集B)的编码数值,而且两种字符集相同编码数值表明相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。 Oracle8i和oracle9i官方文档资料中备有子集-超级对照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。因为US7ASCII是最先的Oracle数据库编码格式,所以有许多字符集是US7ASCII的超集,例如WE8ISO8859P一、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。 2.4 数据库字符集(oracle服务器端字符集) 数据库字符集在建立数据库时指定,在建立后一般不能更改。在建立数据库时,能够指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。 2.4.1字符集 (1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据 (2)用来标示诸如表名、列名以及PL/SQL变量等 (3)用来存储SQL和PL/SQL程序单元等 2.4.2国家字符集: (1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据 (2)国家字符集实质上是为oracle选择的附加字符集,主要做用是为了加强oracle的字符处理能力,由于NCHAR数据类型能够提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了从新定义,只能在Unicode编码中的AF16UTF16和UTF8中选择,默认值是AF16UTF16 2.4.3查询字符集参数 能够查询如下数据字典或视图查看字符集设置状况 nls_database_parameters、props$、v$nls_parameters 查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集 2.4.4修改数据库字符集 按照上文所说,数据库字符集在建立后原则上不能更改。若是须要修改字符集,一般须要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或经过ALTER DATABASE CHARACTER SET语句修改字符集,但建立数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可以使用ALTER DATABASE CHARACTER SET UTF8。 2.5 客户端字符集(NLS_LANG参数) 2.5.1客户端字符集含义 客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端能够看做是能与数据库直接链接的各类应用,例如sqlplus,exp/imp等。客户端字符集是经过设置NLS_LANG参数来设定的。 2.5.2 NLS_LANG参数格式 NLS_LANG=_. Language:显示oracle消息,校验,日期命名 Territory:指定默认日期、数字、货币等格式 Client character set:指定客户端将使用的字符集 例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集 2.5.3客户端字符集设置方法 1)UNIX环境 $NLS_LANG=“simplified chinese”_china.zhs16gbk $export NLS_LANG 编辑oracle用户的profile文件 2)Windows环境 编辑注册表 Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME 2.5.4 NLS参数查询 Oracle提供若干NLS参数定制数据库和用户机以适应本地格式,例若有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,能够经过查询如下数据字典或v$视图查看。 NLS_DATABASE_PARAMETERS--显示数据库当前NLS参数取值,包括数据库字符集取值 NLS_SESSION_PARAMETERS--显示由NLS_LANG 设置的参数,或通过alter session 改变后的参数值(不包括由NLS_LANG 设置的客户端字符集) NLS_INSTANCE_PARAMETE--显示由参数文件init.ora 定义的参数V$NLS_PARAMETERS--显示数据库当前NLS参数取值 2.5.5修改NLS参数 使用下列方法能够修改NLS参数 (1)修改实例启动时使用的初始化参数文件 (2)修改环境变量NLS_LANG (3)使用ALTER SESSION语句,在oracle会话中修改 (4)使用某些SQL函数 NLS做用优先级别:Sql function>alter session>环境变量或注册表>参数文件>数据库默认参数 3 乱码问题 Oracle在数据存储、迁移过程当中常常发生字符乱码问题,归根究竟是因为字符集使用不当引发。下面以使用客户端sqlplus向数据库插入数据为例,说明乱码产生的缘由。 3.1使用客户端sqlplus向数据库存储数据 这个过程存在3个字符集设置 (1)客户端应用字符集 (2)客户端NLS_LANG参数设置 (3)服务器端数据库字符集(Character Set)设置 客户端应用Sqlplus中可以显示什么样的字符取决于客户端操做系统语言环境(客户端应用字符集),但在应用中录入这些字符后,这些字符可否在数据库中正常存储,还与另外两个字符集设置紧密相关,其中客户端NLS_LANG参数主要用于字符数据传输过程当中的转换判断。常见的乱码大体有两种情形: (1)汉字变成问号“?”; 当从字符集A 转换成字符集B时,若是转换字符之间不存在对应关系,NLS_LANG使用替代字符“?”替代没法映射的字符 (2)汉字变成未知字符(虽然有些是汉字,但与原字符含义不一样) 转换存在对应关系,但字符集A 中的字符编码与字符集B 中的字符编码表明不一样含义 3.2发生乱码缘由 乱码产生是因为几个字符集之间转换不匹配形成,分如下几种状况: (注:字符集之间若是不存在子集、超集对应关系时的状况不予考虑,由于这种状况下字符集之间转换必产生乱码) 1)服务器端数据库字符集与客户端应用字符集相同,与客户端NLS_LANG参数设置不一样 若是客户端NLS_LANG字符集是其它两种字符集的子集,转换过程将出现乱码。 解决方法:将三种字符集设置成同一字符集,或NLS_LANG字符集是其它两种字符集的超集 2)服务器端数据库字符集与客户端NLS_LANG参数设置相同,与客户端应用字符集不一样 若是客户端应用字符集是其它两种字符集的超集时,转换过程将出现乱码,但对于单字节编码存储中文问题,可参看本文第5章节的分析 3)客户端应用字符集、客户端NLS_LANG参数设置、服务器端数据库字符集互不相同 此种状况较为复杂,但三种字符集之间只要有不能转换的字符,则必产生乱码 4 单字节编码存储中文问题 因为历史的缘由,早期的oracle没有中文字符集(如oracle六、oracle七、oracle7.1),但有的用户从那时起就使用数据库了,并用US7ASCII字符集存储了中文,或是有的用户在建立数据库时,不考虑清楚,随意选择一个默认的字符集,如WE8ISO8859P1或US7ASCII,而这两个字符集都没有汉字编码,虽然有些时候选用这种字符集好象也能正常使用,但用这种字符集存储汉字信息从原则上说就是错误的,它会给数据库的使用与维护带来一系列的麻烦。 正常状况下,要将汉字存入数据库,数据库字符集必须支持中文,而将数据库字符集设置为US7ASCII等单字节字符集是不合适的。US7ASCII字符集只定义了128个符号,并不支持汉字。另外,若是在SQL*PLUS中可以输入中文,操做系统缺省应该是支持中文的,但若是在NLS_LANG中的字符集设置为US7ASCII,显然也是不正确的,它没有反映客户端的实际状况。但在实际应用中汉字显示倒是正确的,这主要是由于Oracle检查数据库与客户端的字符集设置是一样的,那么数据在客户与数据库之间的存取过程当中将不发生任何转换,可是这实际上致使了数据库标识的字符集与实际存入的内容是不相符的。而在SELECT的过程当中,Oracle一样检查发现数据库与客户端的字符集设置是相同的,因此它也将存入的内容原封不动地传送到客户端,而客户端操做系统识别出这是汉字编码因此可以正确显示。 在这个例子中,数据库与客户端都没有设置成中文字符集,但却能正常显示中文,从应用的角度看好象没问题。然而这里面却存在着极大的隐患,好比在应用length或substr等字符串函数时,就可能获得意外的结果。 对于早期使用US7ASCII字符集数据库的数据迁移到oracle8i/9i中(使用zhs16gbk),因为原始数据已经按照US7ASCII格式存储,对于这种状况,能够经过使用Oracle8i的导出工具,设置导出字符集为US7ASCII,导出后使用UltraEdit等工具打开dmp文件,修改第2、三字符,修改 0001 为0354,这样就能够将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。 为了不在数据库迁移过程当中因为字符集不一样致使的数据损失,oracle提供了字符集扫描工具(character set scanner),经过这个工具咱们能够测试在数据迁移过程当中因为字符集转换可能带来的问题,而后根据测试结果,肯定数据迁移过程当中最佳字符集解决方案。 5 Oracle数据库字符集问题解析 5.1字符集的概念。 咱们知道,电子计算机最初是用来进行科学计算的(因此叫作“计算机”),但随着技术的发展,还须要计算机进行其它方面的应用处理。这就要求计算机不只能处理数值,还能处理诸如文字、特殊符号等其它信息,而计算机自己能直接处理的只有数值信息,因此就要求对这些文字、符号信息进行数值编码,最初的字符集是咱们都很是熟悉的ASCII,它是用7个二进制位来表示128个字符,然后来随着不一样国家、组织的须要,出现了许许多多的字符集,如表示西欧字符的ISO8859系列的字符集,表示汉字的GB2312-80、GBK等字符集。 字符集的实质就是对一组特定的符号,分别赋予不一样的数值编码,以便于计算机的处理。 5.2字符集之间的转换。 字符集多了,就会带来一个问题,好比一个字符,在某一字符集中被编码为一个数值,而在另外一个字符集中被编码为另外一个数值,好比我来创造两个字符集demo_charset1与demo_charset2,在demo_charset1中,我规定了三个符号的编码为:A(0001),B(0010),?(1111);而在demo_charset2中,我也规定了三个符号的编码为:A(1001),C(1011),?(1111),这时我接到一个任务,要编写一个程序,负责在demo_charset1与demo_charset2之间进行转换。因为知道两个字符集的编码规则,对于demo_charset1中的0001,在转换为demo_charset2时,要将其编码改成1001;对于demo_charset1中的1111,转换为demo_charset2时,其数值不变;而对于demo_charset1中的0010,其对应的字符为B,但在demo_charset2没有对应的字符,因此从理论上没法转换,对于全部这类没法转换的状况,咱们能够将它们统一转换为目标字符集中的一个特殊字符(称为“替换字符”),好比在这里咱们能够将?做为替换字符,因此B就转换为了?,出现了信息的丢失;一样道理,将demo_charset2的C字符转换到demo_charset1时,也会出现信息丢失。 因此说,在字符集转换过程当中,若是源字符集中的某个字符在目标字符集中没有定义,将会出现信息丢失。 5.3数据库字符集的选择 咱们在建立数据库时,须要考虑的一个问题就是选择什么字符集与国家字符集(经过create database中的CHARACTER SET与NATIONAL CHARACTER SET子句指定)。考虑这个问题,咱们必需要清楚数据库中都须要存储什么数据,若是只须要存储英文信息,那么选择US7ASCII做为字符集就能够;可是若是要存储中文,那么咱们就须要选择可以支持中文的字符集(如ZHS16GBK);若是须要存储多国语言文字,那就要选择UTF8了。 数据库字符集的肯定,实际上说明这个数据库所能处理的字符的集合及其编码方式,因为字符集选定后再进行更改会有诸多的限制,因此在数据库建立时必定要考虑清楚后再选择。而咱们许多朋友在建立数据库时,不考虑清楚,每每选择一个默认的字符集,如WE8ISO8859P1或US7ASCII,而这两个字符集都没有汉字编码,因此用这种字符集存储汉字信息从原则上说就是错误的。虽然在有些时候选用这种字符集好象也能正常使用,但它会给数据库的使用与维护带来一系列的麻烦,在后面的迭代过程当中咱们将深刻分析。 5.4客户端的字符集 有过一些Oracle使用经验的朋友,大多会知道经过NLS_LANG来设置客户端的状况,NLS_LANG由如下部分组成:NLS_LANG=_.,其中第三部分的本意就是用来指明客户端操做系统缺省使用的字符集。因此按正规的用法,NLS_LANG应该按照客户端机器的实际状况进行配置,尤为对于字符集一项更是如此,这样Oracle就可以在最大程度上实现数据库字符集与客户端字符集的自动转换(固然是若是须要转换的话)。 5.5经过实例加深对基本概念的理解 下面我将引用网友tellin在ITPUB上发表的“CHARACTER SET研究及疑问”帖子,该朋友在帖子中列举了他作的相关实验,并对实验结果提出了一些疑问,我将对他的实验结果进行分析,并回答他的疑问。 5.5.1实验结果分析一 最初由 tellin 发布 设置客户端字符集为US7ASCII D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII 查看服务器字符集为US7ASCII SQL> SELECT * FROM NLS_DATABASE_PARAMETERS; PARAMETER VALUE ------------------------------ ---------------------------------------- NLS_CHARACTERSET US7ASCII 创建测试表 SQL> CREATE TABLE TEST (R1 VARCHAR2(10)); Table created. 插入数据 SQL> INSERT INTO TEST VALUES('东北'); 1 row created. SQL> SELECT * FROM TEST; R1 ---------- 东北 SQL> EXIT 这一部分的实验数据的存取与显示都正确,好象没什么问题,但实际上却隐藏着很大的隐患。 首先,要将汉字存入数据库,而将数据库字符集设置为US7ASCII是不合适的。US7ASCII字符集只定义了128个符号,并不支持汉字。另外,因为在SQL*PLUS中可以输入中文,操做系统缺省应该是支持中文的,但在NLS_LANG中的字符集设置为US7ASCII,显然也是不正确的,它没有反映客户端的实际状况。 但实际显示倒是正确的,这主要是由于Oracle检查数据库与客户端的字符集设置是一样的,那么数据在客户与数据库之间的存取过程当中将不发生任何转换。具体地说,在客户端输入“东北”,“东”的汉字的编码为182(10110110)、171(10101011),“北”汉字的编码为177(10110001)、177(10110001),它们将不作任何变化的存入数据库中,可是这实际上致使了数据库标识的字符集与实际存入的内容是不相符的,从某种意义上讲,这也是一种不一致性,也是一种错误。而在SELECT的过程当中,Oracle一样检查发现数据库与客户端的字符集设置是相同的,因此它也将存入的内容原封不动地传送到客户端,而客户端操做系统识别出这是汉字编码因此可以正确显示。 在这个例子中,数据库与客户端的设置都有问题,但却好象起到了“负负得正”的效果,从应用的角度看倒好象没问题。但这里面却存在着极大的隐患,好比在应用length或substr等字符串函数时,就可能获得意外的结果。另外,若是遇到导入/导出(import /export)将会遇到更大的麻烦。有些朋友在这方面作了大量的测试,如eygle研究了“源数据库字符集为US7ASCII,导出文件字符集为US7ASCII或ZHS16GBK,目标数据库字符集为ZHS16GBK”的状况,他得出的结论是 “若是的是在Oracle92中,咱们发现对于这种状况,不论怎样处理,这个导出文件都没法正确导入到Oracle9i数据库中”、“对于这种状况,咱们能够经过使用Oracle8i的导出工具,设置导出字符集为US7ASCII,导出后修改第2、三字符,修改 0001 为0354,这样就能够将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中”。我想对于这些结论,这样理解可能更合适一些:因为ZHS16GBK字符集是US7ASCII的超级,因此若是按正常操做,这种转换应该没有问题;但出现问题的本质是咱们让本应只存储英文字符的US7ASCII数据库,很是规地存储了中文信息,那么在转化过程当中出现错误或麻烦就没什么奇怪的了,不出麻烦却是有些奇怪了。 因此说要避免这种状况,就是要在创建数据库时选择合适的字符集,不让标签(数据库的字符集设置)与实际(数据库中实际存储的信息)不符的状况发生 5.5.2实验结果分析二 [ 更改客户端字符集为ZHS16GBK D:\>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK D:\>SQLPLUS "/ AS SYSDBA" 没法正常显示数据 SQL> SELECT * FROM TEST; R1 -------------------- 6+11 疑问1:ZHS16GBK为US7ASCII的超集,为何在ZHS16GBK环境下没法正常显示 这主要是由于Oracle检查发现数据库设置的字符集与客户端配置字符集不一样,它将对数据进行字符集的转换。数据库中实际存放的数据为182(10110110)、171(10101011)、177(10110001)、177(10110001),因为数据库字符集设置为US7ASCII,它是一个7bit的字符集,存储在8bit的字节中,则Oracle忽略各字节的最高bit,则182(10110110)就变成了54(0110110),在ZHS16GBK中表明数字符号“6”(固然在其它字符集中也是“6”),一样过程也发生在其它3个字节,这样“东北”就变成了“6+11”。 5.5.3实验结果分析三 最初由 tellin 发布 用ZHS16GBK插入数据 SQL> INSERT INTO TEST VALUES('东北'); 1 row created. SQL> SELECT * FROM TEST; R1 -------------------- 6+11 ?? SQL> EXIT 当客户端字符集设置为ZHS16GBK后向数据库插入“东北”,Oracle检查发现数据库设置的字符集为US7ASCII与客户端不一致,须要进行转换,但字符集ZHS16GBK中的“东北”两字在US7ASCII中没有对应的字符,因此Oracle用统一的“替换字符”插入数据库,在这里为“?”,编码为63(00111111),这时,输入的信息实际上已经丢失,无论字符集设置如何改变(以下面引用的实验结果),第二行SELECT出来的结果也都是两个“?”号(注意是2个,而不是4个)。 更改客户端字符集为US7ASCII D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII D:\>SQLPLUS "/ AS SYSDBA" 没法显示用ZHS16GBK插入的字符集,但能够显示用US7ASCII插入的字符集 SQL> SELECT * FROM TEST; R1 ---------- 东北 ?? 更改服务器字符集为ZHS16GBK SQL> update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET'; 1 row updated. SQL> COMMIT; 更改客户端字符集为ZHS16GBK D:\>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK D:\>SQLPLUS "/ AS SYSDBA" 能够显示之前US7ASCII的字符集,但没法显示用ZHS16GBK插入的数据,说明用ZHS16GBK插入的数据为乱码。 SQL> SELECT * FROM TEST; R1 -------------------- 东北 ?? 须要指出的是,经过“update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';”来修改数据库字符集是很是规做法,极可能引发问题,在这里只是原文引用网友的实验结果。 5.5.4实验结果分析四 SQL> INSERT INTO TEST VALUES('东北'); 1 row created. SQL> SELECT * FROM TEST; R1 -------------------- 东北 ?? 东北 SQL> EXIT 因为此时数据库与客户端的字符集设置均为ZHS16GBK,因此不会发生字符集的转换,第一行与第三行数据显示正确,而第二行因为存储的数据就是63(00111111),因此显示的是“?”号。 更改客户端字符集为US7ASCII D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII D:\>SQLPLUS "/ AS SYSDBA" 没法显示数据 SQL> SELECT * FROM TEST; R1 ---------- ?? ?? ?? 疑问2:第一行数据是用US7ASCII环境插入的,为什么没法正常显示? 将客户端字符集设置改成US7ASCII后进行SELECT,Oracle检查发现数据库设置的字符集为ZHS16GBK,数据须要进行字符集转换,而第一行与第三行的汉字“东”与“北”在客户端字符集US7ASCII中没有对应字符,因此转换为“替换字符”(“?”),而第二行数据在数据库中存的原本就是两个“?”号,因此虽然在客户端显示的三行都是两个“?”号,但在数据库中存储的内容倒是不一样的。 5.5.5实验结果分析五 SQL> INSERT INTO TEST VALUES('东北'); 1 row created. SQL> EXIT 更改客户端字符集为ZHS16GBK D:\>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK D:\>SQLPLUS "/ AS SYSDBA" 没法显示用US7ASCII插入的字符集,但能够显示用ZHS16GBK插入的字符集[/COLOR] SQL> SELECT * FROM TEST; R1 -------------------- 东北 ?? 东北 6+11 SQL> 疑问3:US7ASCII为ZHS16GBK的子集,为什么在US7ASCII环境下插入的数据没法显示? 在客户端字符集设置为US7ASCII时,向字符集为ZHS16GBK的数据库中插入“东北”,须要进行字符转换,“东北”的ZHS16GBK编码为182(10110110)、171(10101011)与177(10110001)、 177(10110001),因为US7ASCII为7bit编码,Oracle将这两个汉字看成四个字符,并忽略各字节的最高位,从而存入数据库的编码就变成了54(00110110)、43(00101011)与49(00110001)、49(00110001),也就是“6+11”,原始信息被改变了。这时,将客户端字符集设置为ZHS16GBK再进行SELECT,数据库中的信息不须要改变传到客户端,第1、三行因为存入的信息没有改变能显示“东北”,而第2、四行因为插入数据时信息改变,因此不能显示原有信息了。 6 两条原则 分析了这么多的内容,但实际上总结起来也很简单,要想在字符集方面少些错误与麻烦,须要坚持两条基本原则: 在数据库端:选择须要的字符集(经过Create Database中的CHARACTER SET与NATIONAL CHARACTER SET子句指定); 在客户端:设置操做系统实际使用的字符集(经过环境变量NLS_LANG设置)。 7 参考 1 《理解ORACLE数据库字符集》 转载于网络,来源不明,内容有删减,谨致感谢。 2 《Oracle数据库字符集问题解析》转载于ITPUB论坛,谨致感谢sql

相关文章
相关标签/搜索