日期:2014-05-16  浏览次数:20836 次

修改ORACLE11G,字符集的问题
ORACLE instance shut down.
SQL> startup mount exclusive  
ORACLE instance started.

Total System Global Area 506368000 bytes
Fixed Size 1337520 bytes
Variable Size 318768976 bytes
Database Buffers 180355072 bytes
Redo Buffers 5906432 bytes
Database mounted.
SQL> alter system enable restricted session;

System altered.

SQL> alter database character set INTERNAL_USE ZHS16GBK;
alter database character set INTERNAL_USE ZHS16GBK
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-01109: database not open


WHY????

------解决方案--------------------
SQL code
-- 3.5 字符集的更改 ( P94 )
-- 数据库创建以后,如果需要修改字符集,通常需要重建数据库,通过导入导出的方式来转换。也可以通过以下方式更改:
ALTER DATABASE CHARACTER SET

-- 注意修改数据库字符集时必须谨慎,修改之前一定要为数据库备份。由于不能回退这项操作,因此可能会造成数据丢失或者损坏。

-- 这是最简单的转换字符集的方式,但并不是总是有效。这个命令在Oracle 8时被引入Oracle,这个操作在本质上并不转换任何数据库字符,
-- 只是简单地更新数据库中所有跟字符集相关的信息。

-- 这意味着只能在新字符集是旧字符集严格超集的情况下使用这种方式转换。所谓超集是指当前字符集中的每一个字符集在新字符集中都可以表示,并使用相同的代码点,
-- 比如很多字符集都是US7ASCII的严格超集。

-- 如果不是超集将获得以下错误:
SQL> ALTER DATABASE CHARACTER SET ZHS16CGB231280;
*
ERROR at line 1:
ORA-12712: new character_set_must bu a superset of old character set

-- 下面来看一个测试(以下测试在Oracle 9.2.0下进行,Oracle 9i较Oracle 8i在编码方面有较大改变,在Oracle 8i中,测试结果可能略有不同):
SQL> select name, value$ from props$ where name like '%NLS%';

NAME                      VALUE$
------------------------- -----------------------------------
NLS_LANGUAGE              AMERICAN
NLS_NCHAR_CHARACTERSET    AL16UTF16
NLS_TERRITORY             AMERICA
NLS_CURRENCY              $
NLS_ISO_CURRENCY          AMERICA
NLS_NUMERIC_CHARACTERS    .,
NLS_CHARACTERSET          AL32UTF8
NLS_CALENDAR              GREGORIAN
NLS_DATE_FORMAT           DD-MON-RR
NLS_DATE_LANGUAGE         AMERICAN
NLS_SORT                  BINARY
NLS_TIME_FORMAT           HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT      DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT        HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT   DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY         $
NLS_COMP                  BINARY
NLS_LENGTH_SEMANTICS      BYTE
NLS_NCHAR_CONV_EXCP       FALSE
NLS_RDBMS_VERSION         10.2.0.4.0

20 rows selected.

create table scott.test(id number(18,0), name varchar2(20));
insert into scott.test(id,name) values(1,'盖');
insert into scott.test(id,name) values(2,'gai');

SQL> select name, dump(name) from scott.test;

......

-- 转换字符集,数据库应该在RESTRICTED模式下进行:
C:\> sqlplus "/ as sysdba"

......

SQL> shutdown immediate;

......

SQL> startup mount;

SQL> ALTER SESSION SET SQL_TRACE=TRUE;

......

SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;

......

SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;

SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;

SQL> ALTER DATABASE OPEN;

SQL> set linesize 140;

SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;

......


SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;

......

-- 在Oracle 9i中,如果数据库存在CLOB类型字段,那么就不允许对字符集进行转换,这时可以去查看alert_<sid>.log日志文件,看CLOB字段存在于哪些表上:
ALTER DATABASE CHARACTER SET ZHS16GBK
 SYS.METASTYLESHEET (STYLESHEET) - CLOB populated
ORA-12716 signalled during: ALTER DATABASE CHARACTER SET ZHS16GBK...

-- 对于不同的情况,Oracle 提供不同的解决方案,如果是用户数据表,一般我们可以把包含CLOB字段的表导出,然后drop掉相关对象,
-- 转换后再导入数据库;对于系统表,可以按照以下方式处理:
SQL> truncate table Metastylesheet;

-- 然后可以继续进行转换:
SQL> ALTER SESSION SET SQL_TRACE=TRUE;

SQL> ALTER DATABASE CHARACTER SET ZHS16GBK;

SQL> ALTER SESSION SET SQL_TRACE=FALSE;

-- 在Oracle 9.2.0中,转换完成以后,可以通过运行catmet.sql脚本来重建Metastylesheet表:
SQL> @?/rdbsm/admin/catmet.sql

-- 转换后的数据:
SQL> select name, value$ from prop$ where name like '%NLS%';

-- 提示
-- 通过设置 sql_trace,可以跟踪很多数据库的后台操作,这个工具是DBA常用的“利器”之一。
strace -o sqlp.log sqlplus "