==oracle 数据库NLS_CHARACTERSET 字符集的修改== 修改Oracle 数据库字符集总结: 修改方式大约有3种: 方法一: (最安全的方法) 数据库创建以后,如果需要修改字符集,通常需要重建数据库,通过导入导出的方式来转换。 方法二: (最常用的方法) 通过 "alter database character set ZHS16GBK;"方式修改,但并不总是有效。该命令在Oracle8时被引入Oracle,这个操作在本质上并不转换任何数据库字符,只是简单的更新数据库中所有跟字符集相关的信息。(意味,你只能在新字符集是旧字符集严格超集的情况下使用这种方式转换。) 方法三: (最不安全的方法) 修改SYS.props$表,使用"update props$ set value$='ZHS16GBK' wherename='NLS_CHARACTERSET';" 方式更改字符集时候,只是修改了 props$表,只完成了十几的十二分之一的内容,存在数据完整性的隐患。(value$值输入了不正确的字符集,后果可能导致数据库无法启动。) 只对更改后的数据有效,即数据库中原来的数据仍以原字符集被存储。 注意: 1.修改数据库字符集时必须谨慎,修改之前一定要做数据库全量备份。(由于不能回退该项操作,因此可能会造成数据丢失或者损坏。) 2.使用 "alter database character set ZHS16GBK;"方式更改字符集时候,至少需要更改12张数据字典表; 3.使用"update props$ set value$='ZHS16GBK' wherename='NLS_CHARACTERSET';" 方式更改字符集时候,只是修改了 props$表,只完成了十几的十二分之一的内容,存在数据完整性的隐患。因此,更改字符集尽量使用正常的途径。 4.设置 sql_trace 跟着后台操作:在 mount 模式(SQL> STARTUPMOUNT;)下面,把会话修改为trace模式(SQL> ALTER SESSION SETSQL_TRACE=TRUE;),可以跟着数据库的后台操作。(sql_trace是DBA的常用利器之一) 5.实际上当我们更新了字符集,数据库启动时会根据数据库的字符集自动的来修改控制文件的字符集,如果字符集可以识别,更新控制文件字符集等于数据库字符集;如果字符集不可识别,那么控制文件字符集更新为US7ASCII。通过更新props$表的方式修改字符集,在Oracle7之后就不应该被使用. 本节重点解释方法二: 通过 "alter database character set ZHS16GBK;"方式修改,但并不总是有效。该命令在Oracle8时被引入Oracle,这个操作在本质上并不转换任何数据库字符,只是简单的更新数据库中所有跟字符集相关的信息。 查询字符集信息: "SQL> select name,value$ from props$ where name like'%NLS%';",结果有二十行。 修改步骤: 注意:转换字符集,数据库应该在RESTRICTED模式下进行. (使用DBA登录数据库) 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 120; SQL> ALTER DATABASE CHARACTER SET ZHS16GBK; 常见问题: 问题1: SQL> ALTER DATABASE CHARACTER SET ZHS16CGB231280; ALTER DATABASE CHARACTER SET ZHS16CGB231280 * ERROR at line 1: ORA-12712: new character set must be a superset of old characterset 原因: 字符集超集问题,所谓超集是指:当前字符集中的每一个字符在新字符集中都可以表示,并使用同样的代码点,比如很多字符集都是US7ASCII的严格超集。如果不是超集,将获得以上错误。 解决方式: SQL> alter database character set internal_use ZHS16GBK; SQL> select * from v$nls_parameters; SQL> SHUTDOWN IMMEDIATE; SQL> STARTUP; 备注: ALTER DATABASE CHARACTERSET操作的内部过程是完全相同的,也就是说INTERNAL_USE提供的帮助就是使Oracle数据库绕过了子集与超集的校验。该方法某些方面有用处,比如测试环境;应用于产品环境大家应该格外小心,除了你以外,没有人会为此带来的后果负责。 问题2: ALTER DATABASE CHARACTER SET ZHS16GBK * ERROR at line 1: ORA-12721: operation cannot execute when other sessions areactive 原因: 字符集超集问题。 解决方式: SQL> alter database character set internal_use ZHS16GBK; SQL> select * from v$nls_parameters; SQL> SHUTDOWN IMMEDIATE; SQL> STARTUP; 问题3: SQL> ALTER DATABASE CHARACTER SET ZHS16GBK; ALTER DATABASE CHARACTER SET ZHS16GBK * ERROR at line 1: ORA-12716: Cannot ALTER DATABASE CHARACTER SET when CLOB dataexists 原因: 数据库存在CLOB类型字段,那么就不允许对字符集进行转换 解决方式: 这时候,我们可以去查看alert.log日志文件,看CLOB字段存在于哪些表上: 内容如: ALTER DATABASE CHARACTER SET ZHS16GBK SYS.METASTYLESHEET (STYLESHEET) - CLOB populated ORA-12716 signalled during: ALTER DATABASE CHARACTER SETZHS16GBK... 对于用户表,可以先将该表导出,然后把该表删掉,等字符转换完毕后在导入。 例子1: SQL> select name,value$ from props$ where name like'%NLS%'; NAME VALUE$ -------------------------------------------------------------------------------------------------------------- NLS_LANGUAGE AMERICAN NLS_TERRITORY AMERICA NLS_CURRENCY $ NLS_ISO_CURRENCY AMERICA NLS_NUMERIC_CHARACTERS ., NLS_CHARACTERSET ZHS16GBK 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_NCHAR_CHARACTERSET AL16UTF16 NLS_RDBMS_VERSION 11.1.0.6.0 20 rows selected SQL> 例子2: SQL> ALTER SESSION SET SQL_TRACE=TRUE; Session altered. SQL> ALTER DATABASE CHARACTER SET ZHS16GBK; Database altered. SQL> ALTER SESSION SET SQL_TRACE=FALSE; Session altered. |