日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

字符集的更改

發(fā)布時間:2024/8/26 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符集的更改 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
字符集的更改?
-- 數(shù)據(jù)庫創(chuàng)建以后,如果需要修改字符集,通常需要重建數(shù)據(jù)庫,通過導入導出的方式來轉換。也可以通過以下方式更改:
ALTER DATABASE CHARACTER SET
-- 注意修改數(shù)據(jù)庫字符集時必須謹慎,修改之前一定要為數(shù)據(jù)庫備份。由于不能回退這項操作,因此可能會造成數(shù)據(jù)丟失或者損壞。
-- 這是最簡單的轉換字符集的方式,但并不是總是有效。這個命令在Oracle 8時被引入Oracle,這個操作在本質上并不轉換任何數(shù)據(jù)庫字符,
-- 只是簡單地更新數(shù)據(jù)庫中所有跟字符集相關的信息。
-- 這意味著只能在新字符集是舊字符集嚴格超集的情況下使用這種方式轉換。所謂超集是指當前字符集中的每一個字符集在新字符集中都可以表示,并使用相同的代碼點,
-- 比如很多字符集都是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;
......
-- 轉換字符集,數(shù)據(jù)庫應該在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中,如果數(shù)據(jù)庫存在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 提供不同的解決方案,如果是用戶數(shù)據(jù)表,一般我們可以把包含CLOB字段的表導出,然后drop掉相關對象,
-- 轉換后再導入數(shù)據(jù)庫;對于系統(tǒng)表,可以按照以下方式處理:
SQL> truncate table Metastylesheet;
-- 然后可以繼續(xù)進行轉換:
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
-- 轉換后的數(shù)據(jù):
SQL> select name, value$ from prop$ where name like '%NLS%';
-- 提示
-- 通過設置 sql_trace,可以跟蹤很多數(shù)據(jù)庫的后臺操作,這個工具是DBA常用的“利器”之一。
strace -o sqlp.log sqlplus "/ as sysdba"
-- 簡單看一下數(shù)據(jù)庫更改字符集時的后臺處理,這里提取了主要的更新部分。
-- 通過以下跟蹤過程,可以看到數(shù)據(jù)庫在更改字符集的時候 ,主要更新了12張數(shù)據(jù)字典表,修改了數(shù)據(jù)庫的原數(shù)據(jù),這也證實了我們以前的說法,
-- 這個更改字符集的操作在本質上并不轉換任何數(shù)據(jù)庫字符,只是簡單地更新數(shù)據(jù)庫中所有跟字符集相關的信息。
......
-- 在這里糾正一個由來已久的錯誤方法,經(jīng)??梢栽诰W(wǎng)上看到這樣的更改字符集的方法,這種方法應該被忘記,絕對不應該被采用:
-- *(1) 用SYS用戶登錄ORACLE。
-- *(2) 查看字符集內(nèi)容
?? ? ? ?SELECT * FROM props$;
-- *(3) 修改字符集
??update props$ set value$='ZHS16GBK' where name='NLS_CHARACTERSET';
??update props$ set value$='AL32UTF8' where name='NLS_CHARACTERSET';


-- 很多人在這個問題上遇到了慘痛的教訓。使用這種方式更改字符集,如果你的value$值輸入了不正確的字符集,那么在Oracle 8i中你的數(shù)據(jù)庫就可能會無法啟動。
-- 這種情況是非常嚴重的,有時候你必須從備份中進行恢復;如果是在Oracle 9i中,可以重新啟動數(shù)據(jù)庫后再修改回正確的字符集。實際上當更新了字符集,
-- 數(shù)據(jù)庫啟動時會根據(jù)數(shù)據(jù)庫的字符集自動地來修改控制文件的字符集,如果字符集可以識別,更新控制文件字符集等于數(shù)據(jù)庫字符集;
-- 如果字符集不可識別,那么控制文件字符集更新為US7ASCII。
-- 以下是我的測試結果,但是嚴禁一切不備份的修改研究,即使是對測試庫的。
SQL> update props$ set value$='EYGLE' where name='NLS_CHARACTERSET';
SQL> COMMIT;
SQL> SELECT name, value$ from props$ where name like '%NLS%';
-- 重新啟動數(shù)據(jù)庫,發(fā)現(xiàn)alter.log文件中記錄如下操作:
Mon Nov 03 16:11:35 2003
Updating character set in controlfile to US7ASCII
Completed: ALTER DATABASE OPEN
-- 啟動數(shù)據(jù)庫后恢復字符集設置:
SQL> update props$ set value$='ZHS16GBK' where name='NLS_CHARACTERSET';
......
SQL> commit;
......
SQL> select name, value$ from props$ where name like '%NLS%';
......
-- 重新啟動數(shù)據(jù)庫后,發(fā)現(xiàn)控制文件的字符集被更新:
Mon Nov 03 16:21:41 2003
Updating character set in controlfile to ZHS16GBK
Completed: ALTER DATABASE OPEN
-- 理解了字符集調用的內(nèi)部操作以后,我們可以輕易地指出,以上方法是不正確的,通過前面“ALTER DATABASE CHARACTER SET”方式更改字符集時,
-- Oracle 至少需要更改12張數(shù)據(jù)字典表,而這種直接更新props$表的方式只完成了其中十二分之一的工作,潛在的完整性隱患是可想而知的。
-- 所以,更改字符集盡量要使用正常的途徑。
識別導出文件的字符集 ( P98 )
-- 在傳統(tǒng)的EXP導出文件中,記錄著導出使用的字符集id,通過查看導出文件頭的第2、3個字節(jié),可以找到十六進制表示的字符集ID,
-- 在Windows上,可以使用 UltraEdit等工具打開dmp文件,查看其導出字符集,如圖3-6所示。
......
exp system/bee56915 file=/u02/exp/scott011.dmp owner=scott
-- 在UNIX環(huán)境上,可以通過以下命令來查看(以下范例來自Solaris平臺),如圖3-7所示。


[oracle@sztyora exp]$ cat scott011.dmp | od -x | head -2
0000000 0003 4501 5058 524f 3a54 3156 2e30 3230
0000020 302e 0a31 5344 5359 4554 0a4d 5552 4553
0000040 5352 380a 3931 0a32 0a30 3032 300a 000a
0000060 0301 0769 00d0 0001 0000 0000 0000 0000
0000100 0015 2020 2020 2020 2020 2020 2020 2020
0000120 2020 2020 2020 2020 2020 2020 2020 2020
0000140 2020 2020 2020 2020 6153 2074 754a 206e
0000160 3632 3120 3a32 3933 353a 2037 3032 3031
0000200 752f 3230 652f 7078 732f 6f63 7474 3130
0000220 2e31 6d64 0070 0000 0000 0000 0000 0000


-- 需要注意的是,在不同平臺,以上命令的輸出可能有所不同,比如在Linux平臺:
[oracle@sztyora exp]$ ?cat scott011.dmp | od -x | head -2
0000000 0003 4501 5058 524f 3a54 3156 2e30 3230
0000020 302e 0a31 5344 5359 4554 0a4d 5552 4553
-- 這是由于 Solaris 和 Linux 的字節(jié)序是不同的,Solaris 是 Big-Endians,Linux 是 Little-Endians,所以Linux上的輸出通過交換可以得到:
-- 字符集和 Solaris 上是一致的,所以也可以通過od的參數(shù)設置顯示格式:
[oracle@sztyora exp]$ cat scott011.dmp | od -t x1 | head -2
0000000 03 00 01 45 58 50 4f 52 54 3a 56 31 30 2e 30 32
0000020 2e 30 31 0a 44 53 59 53 54 45 4d 0a 52 55 53 45
-- Oracle 提供標準函數(shù),對字符集名稱及ID進行轉換:
SQL> select nls_charset_id('ZHS16GBK') from dual;


NLS_CHARSET_ID('ZHS16GBK')
--------------------------
?? ? ? ? ? ? ? ? ? ? ? 852
SQL> select nls_charset_name(852) from dual;
-- select nls_charset_id('AL32UTF8') from dual;
-- select nls_charset_name(873) from dual;
SQL> select to_char('873','xxxx') from dual;


TO_CH
-----
??369
-- 對應圖3-6或圖3-7中的第2、3字節(jié),就知道該導出文件字符集為ZHS16GBK。查詢數(shù)據(jù)庫中有效的字符集可以使用以下腳本:
col nls_charset_id for 9999
col nls_charset_name for a25
col hex_id for a20
select nls_charset_id(value) nls_charset_id,?
?? ? ? value nls_charset_name,
?? ? ? to_char(nls_charset_id(value),'xxxx') hex_id
from v$nls_valid_values
where parameter = 'CHARACTERSET'
?order by nls_charset_id(value);


-- 輸出樣例如下:
......
-- 而對于 Oracle 10g 的 EXPDP 導出文件,一切則要簡單得多,在EXPDP的導出文件開始部分,Oracle 以 XML 格式記錄了數(shù)據(jù)的字符集信息,
-- 以下是一個單表導出文件的頭信息。
......
-- 對于傳統(tǒng)的 DMP 導出文件,在很多時候,當進行導入操作時,已經(jīng)離開了源數(shù)據(jù)庫,這時如果目標數(shù)據(jù)庫的字符集和導出文件不一致,
-- 多半就需要進行特殊處理進行轉換。最常見的轉換發(fā)生在從US7ASCII到ZHS16GBK之間。
-- 由于很多數(shù)據(jù)庫最初以US7ASCII字符集存儲中文,單純通過導入是無法完成字符集轉換的。對于這種情況,可以通過設置導出字符集為US7ASCII,原樣導出數(shù)據(jù);
-- 導出后修改導出文件的第二、第三字符,修改0001 為 0354,這樣就可以將US7ASCII字符集的數(shù)據(jù)正確導入到ZHS16GBK的數(shù)據(jù)庫中。
-- 如圖3-8所示是一個測試例子,我們可以通過UltraEdit等工具的二進制編輯模式修改導出文件:
......
-- 修改完成之后,可以導入修改后的DMP文件:
E:\nls2> set NLS_LANG=AMERICATION_AMERICA.ZHS16GBK
E:\nls2> imp eygle/eygle file=Sus7ascii-Cus7ascii-exp817.dmp fromuser=eygle touser=eygle table=test
......
-- 通過這種方式,最終中文可以被正常導入ZSH16GBK的數(shù)據(jù)庫:
E:\nls2> sqlplus eygle/eygle
......
SQL> select name.dump(name) from test;
......
-- 另外一種可嘗試的方法是使用create database 命令。如果導出文件使用的字符集是US7ASCII,目標數(shù)據(jù)庫的字符集是ZHS16GBK,
-- 就可以使用 create database 的方法來修改,具體操作如下:
SQL> select * from v$nls_parameters;
......
SQL> create database character set us7ascii;
create database character set us7ascii
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL> select * from v$nls_parameters;


-- 然后可以導入數(shù)據(jù):
E:\>nls2> set nls_lang=AMERICAN_AMERICA.US7ASCII
E:\>nls2> imp eygle/eygle file=Su7ascii-Cus7ascii.dmp fromuser=eygle touser=eygle
......
-- 查詢數(shù)據(jù)庫:
E:\nls2> sqlplus eygle/eygle
......
SQL> select * from test;
-- 當發(fā)出“create database character set us7ascii;”命令時,數(shù)據(jù)庫v$nls_parameters中的字符集設置隨之更改,該參數(shù)影響導入進程,
-- 更改后可以正確導入數(shù)據(jù),重起數(shù)據(jù)庫后,該設置恢復。
-- 提示
-- v$nls_parameters 來源于x$nls_parameters,該動態(tài)性能視圖影響導入操作;而nls_database_parameters來源于prop$數(shù)據(jù)表,影響數(shù)據(jù)存儲。
-- 以上方法只應該在不得已的情況下使用,其本質是欺騙數(shù)據(jù)庫,強制導入數(shù)據(jù),但是可能會損失元數(shù)據(jù)。如果要確保數(shù)據(jù)的完整性,應該使用csscan掃描數(shù)據(jù)庫,
-- 找出所有不兼容的字符,然后通過編寫相應的腳本代碼,在轉換之后進行更新,確保數(shù)據(jù)的正確性。
-- 簡單看一下csscan的使用。要使用csscan之前,需要以sys用戶身份創(chuàng)建相應數(shù)據(jù)字典對象:
E:\nls2> sqlplus "/ as sysdba"
.....
SQL> select instance_name from v$instance;
SQL> @?/rdbms/admin/csminst.sql
......
-- 這個腳本創(chuàng)建相應用戶(cmsig)及數(shù)據(jù)字典對象,掃描信息會記錄在相應的數(shù)據(jù)字典表里??梢栽诿钚姓{用這個工具對數(shù)據(jù)庫進行掃描:
E:\nls2> csscan FULL=Y FROMCHAR=ZHS16GBK TOCHAR=US7ASCII LOG=US7check.log CAPTURE=Y ARRAY=1000000 PROCESS=2
-- 然后可以檢查輸出的日志來查看數(shù)據(jù)庫掃描情況:
......
-- 不能轉換的數(shù)據(jù)將會被記錄下來,然后可以根據(jù)這些信息在轉換之后,對數(shù)據(jù)進行相應的更新,確保轉換無誤。
-- 3.7 亂碼的產(chǎn)生 ( P105 )
-- 最后我們來討論一下亂碼的產(chǎn)生。通常在現(xiàn)實環(huán)境中,存在3個字符集設置:
-- *(1) 客戶端應用字符集(Client Application Character Set);
-- *(2) 客戶端NLS_LANG參數(shù)設置;
-- *(3) 服務器端,數(shù)據(jù)庫字符集(Character Set)設置。
-- 由于一個字符在客戶端應用(如SQLPLUS、CMD、NOTEPAD等)中以怎樣的字符顯示取決于客戶端操作系統(tǒng),客戶端能夠顯示怎樣的字符,我們就可以在應用中錄入這些字符。
-- 至于這些字符能否在數(shù)據(jù)庫中正常存儲,就和另外的兩個字符集設置緊密相關了。
-- 在傳輸過程中,客戶端NLS_LANG主要用于進行轉換判斷。如果NLS_LANG等于數(shù)據(jù)庫字符集,則不進行任何轉換直接把字符插入數(shù)據(jù)庫;
-- 如果不同則進行轉換,轉換主要有兩個任務:
-- *(1) 如果存在對應關系,則把相應二進制編碼經(jīng)過映射后(這一步映射以后,所代表的字符可能發(fā)生轉換)傳遞給數(shù)據(jù)庫。
-- *(2) 如果不存在對應關系,則傳遞一個替換字符(不同平臺的替換字符各不相同,最常見的替換字符是“?”)。
-- 數(shù)據(jù)庫字符集,在和客戶端NLS_LANG不同時,會對經(jīng)過NLS_LANG轉換的字符進一步處理:對于?(即不存在對應關系的字符)直接以?形式存放入數(shù)據(jù)庫,
-- 對于其他字符,在NLS_LANG和數(shù)據(jù)庫字符集之間進行轉換后存入。
-- 下面來看一下最為常見的字符集及亂碼的產(chǎn)生。
-- *1) 當NLS_LANG字符集與數(shù)據(jù)庫字符集不同
-- 當NLS_LANG字符集與數(shù)據(jù)庫字符集不同,且NLS_LANG不同于客戶端字符集設置時,存在以下兩種可能。
-- *(1) 客戶端輸入的字符在NLS_LANG中沒有對應的字符,這時無法轉換,NLS_LANG使用替換字符集替代這些無法映射的字符(這一步轉換在TTS中完成),
-- ? ? ?在很多字符集中之個替代字符就是“?”。
-- *(2) 當客戶端的字符在NLS_LANG中對應了不同的字符時,傳遞給數(shù)據(jù)庫以后發(fā)生轉換,存儲的是字符,但是已經(jīng)失去了原數(shù)據(jù),數(shù)據(jù)庫中的字符不再代表客戶端的輸入。
-- ? ? ?而且這個過程不可逆,這也就是為什么很多時候在客戶端輸入的是正常的編碼,而查詢之后會得到未知字符的原因。
......
-- 可以用我們熟悉的字符集做一個簡單的測試(測試環(huán)境是客戶端代碼點對應中文18030字符集,NLS_LANG設置為US7ASCII字符集,
-- 數(shù)據(jù)庫CHARACTER SET為ZHS16GBK)。
C:\> set NLS_LANG=AMERICAN_AMERICA.US7ASCII
C:\> sqlplus eygle/eygle
SQL> insert into test values(1,'測試');
SQL> select name, dump(name) from test;
-- 這時發(fā)現(xiàn),查詢出來的是混亂的字符,把這些字符轉換為二進制就是:
......
-- 來看正確的存儲:
C:\> set nls_lang=AMERICAN_AMERICA.ZHS16GBK
C:\> sqlplus eygle/eygle
SQL> insert into test values(1,'測試');
SQL> column dump(name) for a40
SQL> column name for a20
SQL> select name, dump(name) from test;


NAME ? ? ? ? ? ? ? ? DUMP(NAME)
-------------------- ----------------------------------------
測試 ? ? ? ? ? ? ? ? Typ=1 Len=6: 230,181,139,232,175,149


-------------------------------------------
vi /etc/sysconfig/i18n
LANG="en_US.UTF-8"
SYSFONT="latarcyrheb-sun16"
-------------------------------------------
-- *2) NLS_LANG和數(shù)據(jù)庫字符集相同時:
-- 在這種情況下,數(shù)據(jù)庫端對客戶端傳遞過來的編碼不進行任何轉換(這樣可以提高性能),直接存儲進入數(shù)據(jù)庫,那么這個時候就存在和上面同樣的問題,
-- 如果客戶端傳遞過來的字符集在數(shù)據(jù)庫中有正確的對應就可以正確存儲,如果沒有,就會被替換字符轉換成,亂碼就這樣產(chǎn)生了。
......
-- 來看一個簡單的測試(測試環(huán)境是客戶端代碼點對應中文 18030 字符集,客戶端 NLS_LANG為US7ASCII,數(shù)據(jù)庫字符集為US7ASCII)。
-- 我們知道這個時候存入的數(shù)據(jù),數(shù)據(jù)庫不會進行任何轉換,在以下的測試中,看到中文在US7ASCII字符集下得以正確顯示。
C:\> set nls_lan=AMERICAN_AMERICA.US7ASCII
C:\> sqlplus eygle/eygle
.....
SQL> insert into test values('測試');
SQL> commit;


SQL> select * from test;


SQL> col dump(name) for a30
SQL> select name, dump(name) from test;


......


SQL> select * from nls_database_parameters;


......


?“靠”字的困惑 ( P109 )


......


-- *(1) 客戶端應用字符集(Client Application Character Set)。測試客戶端應用使用命令行工具(cmd.exe),
-- ? ? ?這個工具的字符集決定查詢結果在終端上的輸出顯示,當前命令行工具的字符代碼頁為936,對應的是GBK字符集,如圖3-11所示。
D:\> cmd


D:\> chcp


-- *(2) 客戶端NLS_LANG參數(shù)設置。為了測試異常情況,設置NLS_LANG為AMERICAN_AMERICA.WE8ISO8859P1:
D:\> set NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1


-- *(3) 服務器端,數(shù)據(jù)庫字符集(Character Set)設置。其數(shù)據(jù)庫的字符集為ZHS16GBK。


-- 首先在數(shù)據(jù)庫上創(chuàng)建一個測試表,存儲一點中文數(shù)據(jù):
SQL> create table tcharset (name varchar2(40));


SQL> insert into tcharset values('循序漸進深入淺出');


-- 然后在客戶端WE8ISO8859P1字符集下執(zhí)行查詢:
D:\> set NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1


D:\> sqlplus eygle/eygle@eygle


......


scott@SZTYORA> select * from tcharset;


NAME
----------------------------------------
靠靠靠靠


-- 現(xiàn)在我們看到8個漢字被轉換成4個“靠”字輸出顯示?這是怎么回事呢?


-- 我們知道,Oracle 數(shù)據(jù)庫服務器是傳輸代碼給客戶端的,數(shù)據(jù)本身不存在問題,編碼會原樣傳輸?shù)娇蛻舳?#xff1a;
SQL> select name, dump(name) from tcharset;


NAME ? ? ? ? DUMP(NAME)
------------ -------------------------------------------------------------------------------------------------------------
靠靠靠靠 ? ? Typ=1 Len=24: 229,190,170,229,186,143,230,184,144,232,191,155,230,183,177,229,133,165,230,181,133,229,135,186


-- 那么可以確認存在問題的只是中間發(fā)生的轉換環(huán)節(jié)。由于WE8ISO8859P1是8位的單Byte編碼方案,所以中文漢字編碼在其中不存在對應關系,
-- 也就是無法轉換,此時WE8ISO8859P1字符集會使用一個替換字符來代替中文,這個替換字符是“ ”,也就是一個倒過來的“?”,不同字符集的替換字符,
-- 我們可以通過Locale Builder工具打開字符文件查看,如圖3-12所示。


......


-- 注意這個特殊字符的編碼為BF,那么也就是說,如果無法轉換ZHS16GBK的8個中文字,WE8ISO8859P1將使用8個“ ”來替換,也就是說經(jīng)過替換之后,
-- 我們有了8個BF的編碼,那么我們再來看看8個BF在客戶端的GBK字符集里代表了什么:


-- 通過微軟網(wǎng)站上的936代碼頁我們可以找到如圖3-13所示的圖表。


......


-- 提示
-- 936代碼頁的網(wǎng)址鏈接為 http://www.microsoft.com/globaldev/reference/dbcs/936.htm 。


-- 從圖3-13中可以看到,其中BFBF正好代表漢字“靠”,于是8個BF最后展現(xiàn)出來就變成了4個“靠”字。
-- 也就可以通過ZHS16GBK字符集文件來找到這個編碼,再者是一致的,如圖3-14所示。


......


-- 這也就是不同字符集、應用之間轉換導致的字符集問題。


自定義字符的使用 ( P112 )
-- 很多時候,需要存儲的字符可能在數(shù)據(jù)庫的字符集中并不存在,這時候我們就可以通過客戶端的“True Type造字程序”來對空閑代碼點進行自定義字符的創(chuàng)建。


-- 在Windows上,單擊“開始”---> “運行” ---> 輸入“eudcedit”命令,可以啟動造字程序,
-- 然后用造字程序在字符集ChineseGBK下使用代碼點AAA1創(chuàng)建一個新字進行測試,如圖3-15所示。


......


?更改字符集的內(nèi)部方式 ( P113 )
-- 前面曾經(jīng)提到,通過修改pops$的方式更改字符集在Oracle 7之后是一種極其危險的方式,應該盡量避免。我們又知道,
-- 通過ALTER DATABASE CHARACTER SET更改字符集雖然安全可靠,但是有嚴格的子集和超集和超集的約束,實際上很少能夠用到這種方法。


-- 除了前面提到的幾種方法外,Oracle還存在另外一種更改字符集的方式:通過隱含的內(nèi)部命令強制修改字符集。


-- 當使用模板的種子數(shù)據(jù)庫創(chuàng)建數(shù)據(jù)庫時,在創(chuàng)建腳本中可以看到這樣的一系列命令:
alter system enable restricted session;
alter database "eygle" open resetlogs;
alter database rename global_name to "eygle";
ALTER TABLESPACE TEMP ADD TEMPFILE 'C:\oracle\oradata\eygle\TEMP01.DBF' SIZE 20480K REUSE AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED;
select tablespace_name from dba_tablespaces where tablespace_name='USERS';
select sid, program, serial#, username from v$session;
alter database character set INTERNAL_CONVERT ZHS16GBK;
alter database nation character set INTERNAL_CONVERT AL16UTF16;
alter user sys identified by "&&sysPassword";
alter user system identified by "&&systemPassword";
alter system disable restricted session;


-- 在這里面,可以看到這樣的兩條重要的、Oracle非公開的命令:
alter database character set INTERNAL_CONVERT ZHS16GBK;
alter database national character set INTERNAL_CONVERT AL16UTF16;


-- 如果檢查警告日志文件,可以發(fā)現(xiàn)相關更改操作的痕跡:
alter database character set INTERNAL_CONVERT ZHS16GBK
Updating character set in controlfile to ZHS16GBK


......


-- 在使用這個命令時,Oracle會跳過所有子集及超集的檢查,在任意字符集之間進行強制轉換,所以,使用這個命令時你必須十分小心,并必須清楚這一操作會帶來的風險。


-- 之前講過的內(nèi)容仍然有效,可以使用csscan掃描整個數(shù)據(jù)庫,如果在轉換的字符集之間確認沒有嚴重的數(shù)據(jù)損壞,或者可以使用有效的方式更改,
-- 就可以使用這種方式進行轉換。


-- 這個內(nèi)部命令的用戶引用格式如下:
alter database character set INTERNAL_USE ZHS16CGB231280;


-- 來看一下具體的操作過程及Oracle的內(nèi)部操作:
SQL> shutdown immedaite;


SQL> STARTUP MOUNT;


SQL> ALTER SYSTEM ENABLE RESTRICTED SESION;


SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;


SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;


SQL> ALTER DATABASE OPEN;


SQL> alter session set events '10046 trace name context forever,level 12'


SQL> alter database character set INTERNAL_USE ZHS16CGB231280


-- 這時警告日志文件中的記錄了如下信息:
......


alter database character set INTERNAL_USE ZHS16CGB231280
Updating character set in controlfile to ZHS16CGB231280


......


-- 格式化 10046 跟蹤文件,得到以下信息(摘要):


......


-- 可以看到這個過程和之前ALTER DATABASE CHARACTER SET操作的內(nèi)部過程是完全相同的,
-- 也就是說INTERNAL_USE提供的幫助就是使Oracle數(shù)據(jù)庫繞過了子集與超集的校驗。


-- 這一方法在某些方面是有用處的,比如測試;但應用于產(chǎn)品環(huán)境時就應該格外小心,除了你以外,沒有人會為此帶來的后果負責!


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


ORA-29275: 部分多字節(jié)字符


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

總結

以上是生活随笔為你收集整理的字符集的更改的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。