1. 程式人生 > >修改oracle資料庫字符集編碼

修改oracle資料庫字符集編碼

==oracle 資料庫 NLS_CHARACTERSET 字符集的修改==
修改Oracle 資料庫字符集總結:
修改方式大約有3種:
方法一: (最安全的方法)
資料庫建立以後,如果需要修改字符集,通常需要重建資料庫,通過匯入匯出的方式來轉換。
方法二: (最常用的方法)
通過 "alter database character set ZHS16GBK;" 方式修改,但並不總是有效。該命令在Oracle8時被引入Oracle,這個操作在本質上並不轉換任何資料庫字元,只是簡單的更新資料庫中所有跟字符集相關的資訊。(意味,你只能在新字符集是舊字符集嚴格超集的情況下使用這種方式轉換。)
方法三: (最不安全的方法)
修改SYS.props$表,使用"update props$ set value$='ZHS16GBK' where name='NLS_CHARACTERSET';" 方式更改字符集時候,只是修改了 props$ 表,只完成了十幾的十二分之一的內容,存在資料完整性的隱患。(value$值輸入了不正確的字符集,後果可能導致資料庫無法啟動。)
只對更改後的資料有效,即資料庫中原來的資料仍以原字符集被儲存。

注意:
1.修改資料庫字符集時必須謹慎,修改之前一定要做資料庫全量備份。(由於不能回退該項操作,因此可能會造成資料丟失或者損壞。)
2.使用 "alter database character set ZHS16GBK;" 方式更改字符集時候,至少需要更改12張資料字典表;
3.使用"update props$ set value$='ZHS16GBK' where name='NLS_CHARACTERSET';" 方式更改字符集時候,只是修改了 props$ 表,只完成了十幾的十二分之一的內容,存在資料完整性的隱患。因此,更改字符集儘量使用正常的途徑。
4.設定 sql_trace 跟著後臺操作:在 mount 模式(SQL> STARTUP MOUNT;)下面,把會話修改為trace模式(SQL> ALTER SESSION SET SQL_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 character set
原因:
字符集超集問題,所謂超集是指:當前字符集中的每一個字元在新字符集中都可以表示,並使用同樣的程式碼點,比如很多字符集都是US7ASCII的嚴格超集。如果不是超集,將獲得以上錯誤。
解決方式:
SQL> alter database character set internal_use ZHS16GBK;
SQL> select * from v$nls_parameters;
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP;
備註:
ALTER DATABASE CHARACTER SET操作的內部過程是完全相同的,也就是說INTERNAL_USE提供的幫助就是使Oracle資料庫繞過了子集與超集的校驗。該方法某些方面有用處,比如測試環境;應用於產品環境大家應該格外小心,除了你以外,沒有人會為此帶來的後果負責。

問題2:
ALTER DATABASE CHARACTER SET ZHS16GBK
*
ERROR at line 1:
ORA-12721: operation cannot execute when other sessions are active
原因:
字符集超集問題。
解決方式:
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 data exists
原因:
資料庫存在CLOB型別欄位,那麼就不允許對字符集進行轉換
解決方式:
這時候,我們可以去檢視alert.log日誌檔案,看CLOB欄位存在於哪些表上:
內容如:
ALTER DATABASE CHARACTER SET ZHS16GBK
SYS.METASTYLESHEET (STYLESHEET) - CLOB populated
ORA-12716 signalled during: ALTER DATABASE CHARACTER SET ZHS16GBK...
對於使用者表,可以先將該表匯出,然後把該表刪掉,等字元轉換完畢後在匯入。



例子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.