您好,登錄后才能下訂單哦!
我用的數據庫是oracle11.2.0.4,數據庫字符集是al32utf8。
客戶端就是同一臺機器的windows 7
用window7的客戶端連接
查看windows客戶端中文字符
虛擬機 192.168.10.5 數據庫是test1 數據庫字符集是al32utf8。
C:\Users\Administrator>echo %NLS_LANG% -------查看客戶端字符命令
SIMPLIFIED CHINESE_CHINA.AL32UTF8
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK -----設置客戶端字符命令
數據庫是test1 ,數據庫字符集是al32utf8。
--session 1 設置客戶端字符集為 zhs16gbk(修改注冊表nls_lang項的characterset 為zhs16gbk) 向表中插入兩個中文字符。
C:\Users\Administrator>echo %NLS_LANG%
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
C:\Users\Administrator>sqlplus sys/oracle@test1 as sysdba;
SQL> create table test(col1 number(1),col2 varchar2(10));
SQL> insert into test values(1,'中國'); --1為session 1的標記
1 row created.
SQL> commit;
Commit complete.
SQL> create table test(col1 number(1),col2 varchar2(10));
表已創建。
SQL> insert into test values(1,'中國');
已創建 1 行。
SQL>
-session 2 設置客戶端字符集 al32utf8(修改注冊表nls_lang項的characterset 為al32utf8),與數據庫字符集相同。 向表中插入兩個和session 1相同的中文字符。
C:\Users\Administrator>echo %NLS_LANG%
SIMPLIFIED CHINESE_CHINA.AL32UTF8
C:\Users\Administrator>sqlplus sys/oracle@test1 as sysdba;
SQL*Plus: Release 11.2.0.1.0 Production on 鏄熸湡涓 11鏈?28 10:35:33 2016
Copyright (c) 1982, 2010, Oracle. All rights reserved.
榪炴帴鍒?
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL>
SQL> insert into test values(2,'中國'); --2為session 2的標記
1 row created.
SQL> commit;
Commit complete.
--session 1
SQL> select * from test;
COL1 COL2
---------- --------------------
1 中國
2 ???
--session 2
SQL> select * from test;
COL1 COL2
---------- ----------
1 涓浗
2 中國
SQL>
從session 1和session 2的結果中可以看到,相同的字符(注意,我指的是我們看到的,顯示為相同的字符 中國),在不同的字符集輸入環境(客戶端環境變量)下,顯示成了亂碼。
在zhs16gbk字符集的客戶端,我們看到了utf8字符集客戶端輸入的相同的中文變成了亂碼-->col1=2的col2字段
SQL> select * from test;
COL1 COL2
---------- --------------------
1 中國
2 ???
在utf8字符集客戶端,我們看到zhs16gbk字符集的客戶端輸入的中文變成了另外的字符 -->col1=1的col2字段
SQL> select * from test;
COL1 COL2
---------- ----------
1 涓浗 -----三個字符
2 中國
SQL> select col1,dump(col2,1016) from test;
COL1
----------
DUMP(COL2,1016)
-------------------------------------------------------------
1
Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd
2
Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
不同的客戶端輸入的中文字符,在數據庫中存儲的字符編碼不一致。
session 1 輸入的字符"中國" 在數據庫中存儲的字符編碼為”e4,b8,ad,e5,9b,bd".
session 2 輸入的字符"中國" 在數據庫中存儲的字符編碼為”d6,d0,b9,fa".
會話一、
中國-------e4,b8,ad,e5,9b,bd 數據庫發現客戶端16gbk跟數據庫端的utf8字符不一致 做了字符轉換 首先將客戶端 中國 16gbk的(雙字節)編碼轉成utf8(三字節編碼) 然后存儲下來。
會話二、
中國-------d6,d0,b9,fa 數據庫發現客戶端utf8跟數據庫端的utf8字符一致 欺騙了數據庫端,不做字符轉換,直接以16gbk(雙字節)的字符編碼存儲到數據庫(utf8數據庫編碼為三字節)中。
session 1 輸入的字符"中國" 在數據庫中存儲的字符編碼為”e4,b8,ad,e5,9b,bd"
session 2 輸入的字符"中國" 在數據庫中存儲的字符編碼為”d6,d0,b9,fa"
數據庫看到客戶端的字符集和數據庫的字符集一致,此時oracle將不會再對字符作轉換,因為它認為兩邊的字符編碼是一致的。而此時,
我們欺騙了數據庫,盡管我們將客戶端字符集設置為和數據庫一致,但是其實我們使用的是zhs16gbk字符集編碼(因為此時windows使用的就是這個字符編碼),
對于字符"中國",zhs16gbk字符集里對應的編碼為d6,d0,b9,fa。此時,oracle不加理會的直接將這個編碼保存到了數據庫中。
客戶端的字符集的作用就是告知數據庫端傳輸的字符編碼,跟數據庫端的字符集一致就直接存儲,不一致就字符轉換。
查詢是存儲的字符轉換的逆過程。
session1查詢
SQL> select * from test;
COL1 COL2
---------- --------------------
1 中國
2 ???
當session 1開始查詢時,oracle從表中取出這兩個字符,并按照字符集al32utf8和字符集zhs16gbk的編碼映射表,將它的轉換成zhs16gbk字符編碼,對于編碼“e4,b8,ad,e5,9b,bd”,
它對應的zhs16gbk的字符編碼為"d6,d0,b9,fa",這個編碼對應的字符為”中國“,所以我們看到了這個字符正常顯示出來了,
而對于字符集存儲的al32utf8字符編碼“d6,d0,b9,fa”,
由于我們用于顯示字符的windows環境使用的是zhs16gbk字符集,而在zhs16gbk字符集里面并沒有對應這個編碼的字符或者屬于無法顯示的符號,utf8---16gbk 轉換找不到
于是使用了"?"這樣的字符來替換,這就是為什么我們看到session 2輸入的字符變成了這樣的亂碼。
session2查詢
SQL> select * from test;
COL1 COL2
---------- ----------
1 涓浗
2 中國
SQL>
當session 2開始查詢時,oracle從表中取出這兩個字符,由于客戶端(nls_lang)和數據庫的字符集設置一致,oracle將忽略字符的轉換問題,
于是直接將數據庫中存儲的字符返回給客戶端。對于編碼為"d6,d0,b9,fa"的字符,返回給客戶端,而客戶端顯示所用的字符集正好是zhs16gbk,在這個字符集里,########(雖然客戶端變成ut8,但是轉換回來還是以16gbk的,windows依然是16gbk。)
這個編碼對應的是"中國"兩個字符,所以就正常顯示出來了。
對于字符編碼“e4,b8,ad,e5,9b,bd”,返回到客戶端後,因為在zhs16gbk里采用的是雙字節存儲字符方式,(雖然客戶端變成utf8,但是轉換回來還是以16gbk的,windows依然是16gbk。)
所以這6字節對應了zhs16gbk字符集的3個字符,也就是我們看到的"涓浗"。
導入導出 exp imp 客戶端對字符的影響實驗
創建兩個庫
test1 源數據庫 字符集----------- SIMPLIFIED CHINESE_CHINA.AL32UTF8
test2 目標數據庫 字符集----------- SIMPLIFIED CHINESE_CHINA.16gbk
創建用戶jiang/oracle 建立test表
oracle@linux5:/oracle>export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK" ###########環境變量
SQL> select col1,dump(col2,1016) from test;
COL1
----------
DUMP(COL2,1016)
--------------------------------------------------------------------------------
2
Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
1
Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd
Export: Release 11.2.0.4.0 - Production on 星期一 11月 28 17:05:50 2016
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
連接到: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
已導出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
服務器使用 AL32UTF8 字符集 (可能的字符集轉換)
. 正在導出 pre-schema 過程對象和操作
. 正在導出用戶 JIANG 的外部函數庫名
. 導出 PUBLIC 類型同義詞
. 正在導出專用類型同義詞
. 正在導出用戶 JIANG 的對象類型定義
即將導出 JIANG 的對象...
. 正在導出數據庫鏈接
. 正在導出序號
. 正在導出簇定義
. 即將導出 JIANG 的表通過常規路徑...
. . 正在導出表 TEST導出了 2 行
. 正在導出同義詞
. 正在導出視圖
. 正在導出存儲過程
. 正在導出運算符
. 正在導出引用完整性約束條件
. 正在導出觸發器
. 正在導出索引類型
. 正在導出位圖, 功能性索引和可擴展索引
. 正在導出后期表活動
. 正在導出實體化視圖
. 正在導出快照日志
. 正在導出作業隊列
. 正在導出刷新組和子組
. 正在導出維
. 正在導出 post-schema 過程對象和操作
. 正在導出統計信息
成功終止導出, 沒有出現警告。
導入到test2 ,目標數據庫字符集為16gbk
oracle@linux5:/oracle>imp jiang/oracle@test2 fromuser=jiang touser=jiang file=/backup/test1.dmp log=/backup/testimp.log
Import: Release 11.2.0.4.0 - Production on 星期一 11月 28 17:28:32 2016
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
連接到: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
經由常規路徑由 EXPORT:V11.02.00 創建的導出文件
已經完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的導入
. . 正在導入表 "TEST"導入了 2 行
成功終止導入, 沒有出現警告。
oracle@linux5:/oracle>
SQL> select * from test;
COL1 COL2
---------- ----------
2 ???
1 中國
SQL> select col1,dump(col2,1016) from test;
COL1
----------
DUMP(COL2,1016)
--------------------------------------------------------------------------------
2
Typ=1 Len=4 CharacterSet=ZHS16GBK: a3,bf,3f,3f
1
Typ=1 Len=4 CharacterSet=ZHS16GBK: d6,d0,b9,fa ------------2個字節一個漢字, 16gbk編碼存儲 數據庫做了數字編碼轉換工作。
SQL>
參考 http://blog.csdn.net/wuweilong/article/details/39694531
源端數據庫test1 (1)字符集為utf8 →EXP客戶端(2)→IMP客戶端(3)→目標數據庫(4) test2字符集為16gbk,
數據在遷移過程中要經歷如上的4個點,數據在流動過程中(如上的3個箭頭)需要依次比較箭頭兩端的字符集,
如果相同則不轉換,如果不同則進行轉換。如果相鄰的兩個點之間設置的字符集均不相同,則需要轉換3次。
最好的設置方式是,因為(1)(4)數據庫的字符集是固定的,則設置客戶端的字符集(2)(3)均與(1)相同,
這樣最多只在(3)→(4)的過程中發生一次字符集的轉換。但是前提是(4)的字符集必須是(1)的的字符集的超集。客戶端字符集是通過環境變量NLS_LANG來設置。
寫入數據----字符轉換過程
數據庫端通過簡單的判斷跟 客戶端環境變量的字符集 是否一致進行字符轉換 一致則不轉換,直接存儲到數據庫中,不一致則字符轉換。
客戶端的字符集的作用就是告知數據庫端傳輸的字符編碼
數據庫看到客戶端的字符集和數據庫的字符集一致,此時oracle將不會再對字符作轉換,因為它認為兩邊的字符編碼是一致的。而此時,
我們欺騙了數據庫,盡管我們將客戶端字符集設置為和數據庫一致,但是其實我們使用的windows7是zhs16gbk字符集編碼(因為此時windows使用的就是這個字符編碼),
對于字符"中國",zhs16gbk字符集里對應的編碼為d6,d0,b9,fa。此時,oracle不加理會的直接將這個編碼保存到了數據庫中。
查找數據----字符轉換過程(win7 16gbk一定)
當session 1開始查詢時,oracle從表中取出這兩個字符,并按照字符集al32utf8和字符集zhs16gbk的編碼映射表,將它的轉換成zhs16gbk字符編碼,對于編碼“e4,b8,ad,e5,9b,bd”,
它對應的zhs16gbk的字符編碼為"d6,d0,b9,fa",這個編碼對應的字符為”中國“,所以我們看到了這個字符正常顯示出來了,3---2
而對于字符集存儲的al32utf8字符編碼“d6,d0,b9,fa”,
由于我們用于顯示字符的windows環境使用的是zhs16gbk字符集,而在zhs16gbk字符集里面并沒有對應這個編碼的字符或者屬于無法顯示的符號,utf8---16gbk 轉換找不到
于是使用了"?"這樣的字符來替換,這就是為什么我們看到session 2輸入的字符變成了這樣的亂碼。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。