四川大凉山有宝石吗:oracle字符集问题

来源:百度文库 编辑:中财网 时间:2024/05/05 14:28:39
新建了一台服务器,搭了oracle10g的环境,导出数据的时候,总是报错

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)网上搜了一下,说是客户端的nls_lang和数据库端的不一样,所以在环境变量里设置一个nls_lang=simplified chinese_china.zhs16gbk,问题解决 ————————————————————偶是分割线——————————————————增加一些网上搜到的资料,学习学习  1)创建数据库时:

Character setnational character set分别代表数据库字符集和国家字符集:

CREATE DATABASE zhangyu

MAXINSTANCES 1

MAXLOGHISTORY 1

MAXLOGFILES 5

MAXLOGMEMBERS 3

MAXDATAFILES 100

controlfile reuse

DATAFILE 'E:\zhangyu\oradata\zhangyu\system01.dbf' SIZE 250M REUSE

autoextend on

MAXSIZE UNLIMITED

sysaux datafile 'E:\zhangyu\oradata\zhangyu\sysaux01.dbf' size 200M

autoextend on

maxsize unlimited

DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE 'E:\zhangyu\oradata\zhangyu\temp01.dbf' SIZE 40M REUSE autoextend on

MAXSIZE UNLIMITED

UNDO TABLESPACE "UNDOTBS1" DATAFILE 'E:\zhangyu\oradata\zhangyu\undotbs01.dbf' SIZE 200M REUSE autoextend on

MAXSIZE UNLIMITED

CHARACTER SET ZHS16GBK

NATIONAL CHARACTER SET AL16UTF16

LOGFILE GROUP 1 ('E:\zhangyu\oradata\zhangyu\redo01.log') SIZE 102400K,

GROUP 2 ('E:\zhangyu\oradata\zhangyu\redo02.log') SIZE 102400K,

GROUP 3 ('E:\zhangyu\oradata\zhangyu\redo03.log') SIZE 102400K

国家字符集的作用就是来存储nchar,nvarchar2,nclob等类似数据类型。

2)常见中文字符集:

sys@ZHANGYU>select parameter,value from v$nls_valid_values where upper(parameter)='CHARACTERSET' and ISDEPRECATED='FALSE' and value like 'ZH%';

查询结果中zhs开头的是simplified(简体中文的),zht开头的是 Trad(繁体,传统字体)

另外看下字符参数命名规则:比如zhs16gbk,其中zhs代表语言,这里是简体中文;

16代表16bit(2byte),即可以代表2^16=65536-1个字符;

Gbk代表字符集。

再看us7ascii就代表美国,7bitascii字符集;

还有al6utf16代表所有语言通用(all),16bitutf16字符集等等.

3)字符集的转换

Alter database character set

sys@ZHANGYU>alter database character set zhs16gbk;

alter database character set zhs16gbk

*

1 行出现错误:

ORA-12719: 操作要求数据库处于 RESTRICTED 模式下

且在转换字符集之前一定要确定目标字符集是当前字符集的严格超集

严格超集的条件:

一个字符集里包含另一个字符集中的所有字符,并且相同字符的编码要一样;

满足这两个条件才行。

查看当前非线性变量:

sys@ZHANGYU>select * from v$nls_parameters;

sys@ZHANGYU>select * from v$nls_parameters where parameter in('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');

    改变字符集:

   改变字符集前一定要确定字符间之间的超集关系,下面在我的库上测试,由于不知道zhs16gbk的严格超集,所以没有改变字符集,仅是演示下方式:

sys@ZHANGYU>startup mount;

sys@ZHANGYU>alter system set job_queue_processes=0;

sys@ZHANGYU>alter system set aq_tm_processes=0;

上面两个参数我也不知道啥意思,照做就是;想了解的可以查下官方的reference

sys@ZHANGYU>alter system enable restricted session;

sys@ZHANGYU>alter database open;

sys@ZHANGYU>exec dbms_monitor.session_trace_enable();

sys@ZHANGYU>alter database character set zhs16gbk;

sys@ZHANGYU>exec dbms_monitor.session_trace_disable();

启动另一个session:

sys@ZHANGYU>select b.spid from v$session a,v$process b where a.paddr=b.addr and a.username='SYS';

SPID

------------

3328

1656

sys@ZHANGYU>show parameter user_dump_dest

找到trace文件不是1656就是3328,总有一个的。

结果是1656

Trcsess output=E:\test.trc session=325.3 E:\zhangyu\oradata\admin\zhangyu\udump\zhangyu_ora_1656.trc

update col$ set charsetid = :1 where charsetform = :2

update argument$ set charsetid = :1 where charsetform = :2

update collection$ set charsetid = :1 where charsetform = :2

update attribute$ set charsetid = :1 where charsetform = :2

update parameter$ set charsetid = :1 where charsetform = :2

update result$ set charsetid = :1 where charsetform = :2

update partcol$ set spare1 = :1 where charsetform = :2

update subpartcol$ set spare1 = :1 where charsetform = :2

update props$ set value$ = :1 where name = :2

等等,其实更新字符集就是更新这些数据字典表。


3)字符集对导入导出的影响:

   在客户端进行导出文件时,最好将客户端的nls_lang设置成和数据库端一样的,这样避免发生不必要的转换。而将导出文件再导入到另一个数据库时,也同样将客户端的字符集设置成和数据库端一样的;

上面这样做之后,通常只会最多发生一次数据库字符集的转换(很明显)。

执行导入时主要存在以下两种情况:

   源数据库和目标数据库具有相同的字符集,这时只要设置nls_lang等于数据库字符集即可,前提是导出使用的和前两者一样的,即三者字符集调协一样,这样就不需要进行转换。

   源数据库和目标数据库字符集不同时,我们可以在导出时使用和数据库一样的字符集,而在导入时也是设置和导出时一样的字符集,这样字符集转换只发生在目标数据库上一次。

   下面进行一将从演示:

确定源数据库的字符集,只要进行导出一个小的表就可以实现:

C:\>echo %nls_lang%

american_america.us7ascii

C:\>exp scott/tiger file=e:\scott_dept.dmp tables=dept

Connected to: Personal Oracle Database 10g(个人版) Release 10.2.0.1.0 - Production

With the Partitioning, OLAP and Data Mining options

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)

根据上面的信息我们得知目标数据库使用的是zhs16gbk字符集,所以:

C:\>set nls_lang=simplified chinese_china.zhs16gbk

C:\>exp scott/tiger file=e:\dept_emp.dmp tables=dept,emp

连接到: Personal Oracle Database 10g Release 10.2.0.1.0 - Production

With the Partitioning, OLAP and Data Mining options

已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集

即将导出指定的表通过常规路径...

. . 正在导出表                            DEPT导出了           4

. . 正在导出表                             EMP导出了          14

成功终止导出, 没有出现警告。

    下面进行导入:

C:\>echo %nls_lang%

simplified chinese_china.zhs16gbk

C:\>imp test/tiger file=E:\dept_emp.dmp fromuser=scott touser=test tables=dept,emp

经由常规路径由 EXPORT:V10.02.01 创建的导出文件

警告: 这些对象由 SCOTT 导出, 而不是当前用户

已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入

. 正在将 SCOTT 的对象导入到 TEST

. . 正在导入表                          "DEPT"导入了           4

. . 正在导入表                           "EMP"导入了          14

即将启用约束条件...

成功终止导入, 没有出现警告。

不同字符集的转换方式:

test@orcl>create table test(x int,y varchar2(10));

test@orcl>insert into test values(1,'张玉');

test@orcl>insert into test values(2,'李明');

Commit;

C:\>set nls_lang=american_america.us7ascii

C:\>exp test/tiger file=e:\test.dmp tables=test

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses ZHS16GBK character set (possible charset conversion)

导出时发生了转换

C:\>imp scott/tiger file=e:\test.dmp fromuser=test touser=scott tables=test

import done in US7ASCII character set and AL16UTF16 NCHAR character set

import server uses ZHS16GBK character set (possible charset conversion)

两次发生转换。

看看导入后效果:

scott@orcl>select * from test;

      X    Y

---------- ----------

       1 张玉

       2 李明

 

5)识别导出文件的字符集:

scott@orcl>select nls_charset_id('zhs16gbk') from dual;

NLS_CHARSET_ID('ZHS16GBK')

             --------------------------

                        852

scott@orcl>select nls_charset_name(852) from dual;

NLS_CHAR

--------

ZHS16GBK

sys@orcl>select to_char('1244','xxxx') from dual;

TO_CH

-----

   4dc

十进制转换为十六进制(十六进制一般以0x开头)

查询系统有效字符集:

Select nls_charset_id(value) char_id,to_char(nls_charset_id(value),'xxxx'),value from v$nls_valid_values where parameter='CHARACTERSET' and ISDEPRECATED='FALSE';

   其实在进行导入导出时,我们要考虑的莫非就是以下四种环境的字符集:

l Imp 环境下nls_lang的设置

l Exp 环境下 nls_lang的设置

l S_server(源数据库字符集)

l O_server(目标数据库字符集)

   另外我们还可以利用UEStudioUE)编辑器来进行相应的查看:

UE打开刚才的test.dmp导出文件,查看第23字节内容

上面是00 01

sys@orcl>select nls_charset_name(1) from dual;

NLS_CHAR

--------

US7ASCII

正是us7ascii

当然如果你想改变字符集,比如将字符集改成zhs16gbk,只要将上面的前23字节改成相应的字符id就行了:

sys@orcl>select nls_charset_id('zhs16gbk') from dual;

NLS_CHARSET_ID('ZHS16GBK')

--------------------------

                        852

还要注意UE是显示16进制数的,所以转换成以下:

Select to_char('852','xxxx') from dual;

TO_CH

-----

   354

6)使用oracle提供的字符集扫描工具--CSSCANcharacter set scan)

这个工具是扫描数据库并找出所有不兼容的字符,然后通过编写相应的脚本及代码,转换之后进行更新,确保数据的正确性。

   范例:

使用前必须创建相应数据字典对象,利用csminst.sql脚本创建:

sys@orcl>@F:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\csminst.sql

这个脚本创建相应用户(csmig)及数据字典对象,扫描信息会记录在相应的数据字典表里。

C:\>csscan full=y fromchar=zhs16gbk tochar=us7ascii log=E:\us7check.log capture=

y array=1000000 process=2

Username: system

Password:

   不能转换的数据将会被记录下来,可以在这些信息转换之后,对数据进行相应的更新,确保转换无误。


转自http://hi.baidu.com/linuxocp/blog/item/3301704679ee9740510ffe3c.html