背景
闲言少述,继续测试数据库字符集相关的知识,前几文链接如下:
oracle数据库字符集characterset迁移及变更系列一
http://blog.itpub.net/9240380/viewspace-1849953/
本文主要熟悉下数据库字符集迁移要考虑一些因素。
结论
1,zhs16gbk及al32utf8,消耗的空间是相同的,但二者采用编码是不同的
2,如果源字符集与目标字符集不相同,导入时会根据目标数据库字符集把数据进行重组然后存储
3,基于char固定宽度的字符数据,如果从zhs16gbk到al32utf8,会提示如下错误信息:
Column 1 我们
IMP-00019: row rejected due to ORACLE error 12899
IMP-00003: ORACLE error 12899 encountered
ORA-12899: value too large for column "SCOTT"."T_CHARSET_BAK"."A" (actual: 13, maximum: 10)
为了解决上述问题,有2种方法:
A,根据报错增加迁移表的列长度,然后重新IMP数据即可
B,配置参数blank_trimming=true,不过要重启库方可生效,即移除列尾部的空格字符
4,与CHAR不同,同样是上述的测试环境,如果是VARCHAR2,则可以迁移成功,可见VARCHAR2的优点明显高于CHAR,且消耗空间小,性能更高
所以在设计数据库时要考虑到这些因素
5,同样是基于上述的测试环境,可以把字符数据定义为clob,就可以避免VARCHAR或CHAR类型引发的数据损失或丢失或破坏
6,数据库用户及密码只能是ASCII字符,不能是非ASCII字符,否则数据会无法迁移,且会报错退出
IMP-00058: ORACLE error 1017 encountered
ORA-01017: invalid username/password; logon deniedUsername:
Password:
不过可以基于源数据库的用户,在目标库构建对应权限的新用户,然后IMP FROMUSER TOUSER即可
当然最高效的方法就是在迁移数据时,确保源数据库的用户密码只能包括ASCII字符
分析思路
测试
---为了测试不同数据库字符集之间的变更及迁移的原理,DBCA创建了不同数据库字符集的数据库实例
[oracle@seconary admin]$ ll
total 24
drwxr-x--- 5 oracle oinstall 4096 Nov 29 18:58 charzhs --ZHS16GBK
drwxr-x--- 5 oracle oinstall 4096 Apr 17 2014 guowang --WE8MSWIN1252
drwxr-x--- 5 oracle oinstall 4096 Sep 11 00:44 newb
drwxr-x--- 5 oracle oinstall 4096 Nov 28 16:45 onetime
drwxr-xr-x 3 oracle oinstall 4096 Aug 28 2013 second
drwxr-x--- 5 oracle oinstall 4096 Nov 29 18:35 utf8char -- AL32UTF8
--先看下不同数据库字符集的空间占用差异
---al32utf8
[oracle@seconary admin]$ export ORACLE_SID=utf8char
SQL> conn /as sysdba
Connected.
SQL> alter user scott identified by system account unlock;
User altered.
SQL> conn scott/system
Connected.
SQL> create table t_charset(a char(10));
Table created.
SQL> insert into t_charset values('我们');
1 row created.
SQL> commit;
Commit complete.
SQL> insert into t_charset select * from t_charset;
1 row created.
SQL> insert into t_charset select * from t_charset;
2 rows created.
中间略
SQL> insert into t_charset select * from t_charset;
262144 rows created.
SQL> commit;
Commit complete.
SQL>
SQL> select count(*) from t_charset;
COUNT(*)
----------
524288
SQL> select segment_name,bytes from user_segments where lower(segment_name)='t_charset';
SEGMENT_NAME BYTES
-------------------------------------------------- ----------
T_CHARSET 10485760
SQL> select a,dump(a) from t_charset where rownum<=10;
A DUMP(A)
---------- ----------------------------------------------------------------------------------------------------
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
我们 Typ=96 Len=10: 233,142,180,230,136,156,230,187,145,32
10 rows selected.
--zhs16gbk
SQL> conn scott/system
Connected.
SQL> create table t_charset(a char(10));
Table created.
SQL> insert into t_charset values('我们');
1 row created.
SQL> commit;
SQL> select count(*) from t_charset;
COUNT(*)
----------
524288
可见zhs16gbk及al32utf8基于中文字符消耗的空间是相同的
SQL> select segment_name,bytes from user_segments where lower(segment_name)='t_charset';
SEGMENT_NAME BYTES
--------------------------------------------------------------------------------- ----------
T_CHARSET 10485760
不过2种数据库字符集采用虽然都是10个字节,但底层采用的内部编码不一样
SQL> select a,dump(a) from t_charset where rownum<=10;
A DUMP(A)
------------------------------ ----------------------------------------------------------------------------------------------------
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
我们 Typ=96 Len=10: 230,136,145,228,187,172,32,32,32,32
10 rows selected.
---测试下基于2种数据库字符集不同,EXP以及IMP的情况,al3