日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Oracle數(shù)據(jù)庫字符集問題解析

瀏覽:27日期:2023-11-20 11:24:58
經(jīng)常看到一些朋友問Oracle字符集方面的問題,我想以迭代的方式來介紹一下。第一次迭代:把握字符集方面的基本概念。 有些朋友可能會認為這是多此一舉,但實際上正是由于對相關基本概念把握不清,才導致了諸多問題和疑問。首先是字符集的概念。我們知道,電子計算機最初是用來進行科學計算的(所以叫做“計算機”),但隨著技術的發(fā)展,還需要計算機進行其它方面的應用處理。這就要求計算機不僅能處理數(shù)值,還能處理諸如文字、非凡符號等其它信息,而計算機本身能直接處理的只有數(shù)值信息,所以就要求對這些文字、符號信息進行數(shù)值編碼,最初的字符集是我們都非常熟悉的ASCII,它是用7個二進制位來表示128個字符,而后來隨著不同國家、組織的需要,出現(xiàn)了許許多多的字符集,如表示西歐字符的ISO8859系列的字符集,表示漢字的GB2312-80、GBK等字符集。字符集的實質就是對一組特定的符號,分別賦予不同的數(shù)值編碼,以便于計算機的處理。字符集之間的轉換。字符集多了,就會帶來一個問題,比如一個字符,在某一字符集中被編碼為一個數(shù)值,而在另一個字符集中被編碼為另一個數(shù)值,比如我來創(chuàng)造兩個字符集demo_charset1與demo_charset2,在demo_charset1中,我規(guī)定了三個符號的編碼為:A(0001),B(0010),?(1111);而在demo_charset2中,我也規(guī)定了三個符號的編碼為:A(1001),C(1011),?(1111),這時我接到一個任務,要編寫一個程序,負責在demo_charset1與demo_charset2之間進行轉換。由于知道兩個字符集的編碼規(guī)則,對于demo_charset1中的0001,在轉換為demo_charset2時,要將其編碼改為1001;對于demo_charset1中的1111,轉換為demo_charset2時,其數(shù)值不變;而對于demo_charset1中的0010,其對應的字符為B,但在demo_charset2沒有對應的字符,所以從理論上無法轉換,對于所有這類無法轉換的情況,我們可以將它們統(tǒng)一轉換為目標字符集中的一個非凡字符(稱為“替換字符”),比如在這里我們可以將?作為替換字符,所以B就轉換為了?,出現(xiàn)了信息的丟失;同樣道理,將demo_charset2的C字符轉換到demo_charset1時,也會出現(xiàn)信息丟失。所以說,在字符集轉換過程中,假如源字符集中的某個字符在目標字符集中沒有定義,將會出現(xiàn)信息丟失。數(shù)據(jù)庫字符集的選擇。我們在創(chuàng)建數(shù)據(jù)庫時,需要考慮的一個問題就是選擇什么字符集與國家字符集(通過create database中的CHARACTER SET與NATIONAL CHARACTER SET子句指定)。考慮這個問題,我們必須要清楚數(shù)據(jù)庫中都需要存儲什么數(shù)據(jù),假如只需要存儲英文信息,那么選擇US7ASCII作為字符集就可以;但是假如要存儲中文,那么我們就需要選擇能夠支持中文的字符集(如ZHS16GBK);假如需要存儲多國語言文字,那就要選擇UTF8了。數(shù)據(jù)庫字符集的確定,實際上說明這個數(shù)據(jù)庫所能處理的字符的集合及其編碼方式,由于字符集選定后再進行更改會有諸多的限制,所以在數(shù)據(jù)庫創(chuàng)建時一定要考慮清楚后再選擇。而我們許多朋友在創(chuàng)建數(shù)據(jù)庫時,不考慮清楚,往往選擇一個默認的字符集,如WE8ISO8859P1或US7ASCII,而這兩個字符集都沒有漢字編碼,所以用這種字符集存儲漢字信息從原則上說就是錯誤的。雖然在有些時候選用這種字符集好象也能正常使用,但它會給數(shù)據(jù)庫的使用與維護帶來一系列的麻煩,在后面的迭代過程中我們將深入分析。客戶端的字符集。有過一些Oracle使用經(jīng)驗的朋友,大多會知道通過NLS_LANG來設置客戶端的情況,NLS_LANG由以下部分組成:NLS_LANG=<Language>_<Territory>.<Clients Characterset>,其中第三部分<Clients Characterset>的本意就是用來指明客戶端操作系統(tǒng)缺省使用的字符集。所以按正規(guī)的用法,NLS_LANG應該按照客戶端機器的實際情況進行配置,尤其對于字符集一項更是如此,這樣Oracle就能夠在最大程度上實現(xiàn)數(shù)據(jù)庫字符集與客戶端字符集的自動轉換(當然是假如需要轉換的話)。總結一下第一次迭代的重點:字符集:將特定的符號集編碼為計算機能夠處理的數(shù)值;字符集間的轉換:對于在源字符集與目標字符集都存在的符號,理論上轉換將不會產(chǎn)生信息丟失;而對于在源字符集中存在而在目標字符集中不存在的符號,理論上轉換將會產(chǎn)生信息丟失;數(shù)據(jù)庫字符集:選擇能夠包含所有將要存儲的信息符號的字符集;客戶端字符集設置:指明客戶端操作系統(tǒng)缺省使用的字符集。第二次迭代:通過實例加深對基本概念的理解 下面我將引用網(wǎng)友tellin在ITPUB上發(fā)表的“CHARACTER SET研究及疑問”帖子,該朋友在帖子中列舉了他做的相關實驗,并對實驗結果提出了一些疑問,我將對他的實驗結果進行分析,并回答他的疑問。實驗結果分析一quote: --------------------------------------------------------------------------------最初由 tellin 發(fā)布設置客戶端字符集為US7ASCII D:>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII查看服務器字符集為US7ASCII SQL> SELECT * FROM NLS_DATABASE_PARAMETERS;PARAMETER VALUE------------------------------ ----------------------------------------NLS_CHARACTERSET US7ASCII 建立測試表 SQL> CREATE TABLE TEST (R1 VARCHAR2(10));Table created.插入數(shù)據(jù)SQL> INSERT INTO TEST VALUES('東北');1 row created.SQL> SELECT * FROM TEST;R1----------東北SQL> EXIT--------------------------------------------------------------------------------;這一部分的實驗數(shù)據(jù)的存取與顯示都正確,好象沒什么問題,但實際上卻隱藏著很大的隱患。首先,要將漢字存入數(shù)據(jù)庫,而將數(shù)據(jù)庫字符集設置為US7ASCII是不合適的。US7ASCII字符集只定義了128個符號,并不支持漢字。另外,由于在SQL*PLUS中能夠輸入中文,操作系統(tǒng)缺省應該是支持中文的,但在NLS_LANG中的字符集設置為US7ASCII,顯然也是不正確的,它沒有反映客戶端的實際情況。但實際顯示卻是正確的,這主要是因為Oracle檢查數(shù)據(jù)庫與客戶端的字符集設置是同樣的,那么數(shù)據(jù)在客戶與數(shù)據(jù)庫之間的存取過程中將不發(fā)生任何轉換。具體地說,在客戶端輸入“東北”,“東”的漢字的編碼為182(10110110)、171(10101011),“北”漢字的編碼為177(10110001)、177(10110001),它們將不做任何變化的存入數(shù)據(jù)庫中,但是這實際上導致了數(shù)據(jù)庫標識的字符集與實際存入的內容是不相符的,從某種意義上講,這也是一種不一致性,也是一種錯誤。而在SELECT的過程中,Oracle同樣檢查發(fā)現(xiàn)數(shù)據(jù)庫與客戶端的字符集設置是相同的,所以它也將存入的內容原封不動地傳送到客戶端,而客戶端操作系統(tǒng)識別出這是漢字編碼所以能夠正確顯示。在這個例子中,數(shù)據(jù)庫與客戶端的設置都有問題,但卻好象起到了“負負得正”的效果,從應用的角度看倒好象沒問題。但這里面卻存在著極大的隱患,比如在應用length或substr等字符串函數(shù)時,就可能得到意外的結果。另外,假如碰到導入/導出(import /eXPort)將會碰到更大的麻煩。有些朋友在這方面做了大量的測試,如eygle研究了“源數(shù)據(jù)庫字符集為US7ASCII,導出文件字符集為US7ASCII或ZHS16GBK,目標數(shù)據(jù)庫字符集為ZHS16GBK”的情況,他得出的結論是 “假如的是在Oracle92中,我們發(fā)現(xiàn)對于這種情況,不論怎樣處理,這個導出文件都無法正確導入到Oracle9i數(shù)據(jù)庫中”、“對于這種情況,我們可以通過使用Oracle8i的導出工具,設置導出字符集為US7ASCII,導出后修改第二、三字符,修改 0001 為0354,這樣就可以將US7ASCII字符集的數(shù)據(jù)正確導入到ZHS16GBK的數(shù)據(jù)庫中”。我想對于這些結論,這樣理解可能更合適一些:由于ZHS16GBK字符集是US7ASCII的超級,所以假如按正常操作,這種轉換應該沒有問題;但出現(xiàn)問題的本質是我們讓本應只存儲英文字符的US7ASCII數(shù)據(jù)庫,非常規(guī)地存儲了中文信息,那么在轉化過程中出現(xiàn)錯誤或麻煩就沒什么希奇的了,不出麻煩倒是有些希奇了。所以說要避免這種情況,就是要在建立數(shù)據(jù)庫時選擇合適的字符集,不讓標簽(數(shù)據(jù)庫的字符集設置)與實際(數(shù)據(jù)庫中實際存儲的信息)不符的情況發(fā)生。實驗結果分析二 quote: --------------------------------------------------------------------------------[ 更改客戶端字符集為ZHS16GBKD:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBKD:>SQLPLUS '/ AS SYSDBA'無法正常顯示數(shù)據(jù)SQL> SELECT * FROM TEST;R1--------------------6+11疑問1:ZHS16GBK為US7ASCII的超集,為什么在ZHS16GBK環(huán)境下無法正常顯示 --------------------------------------------------------------------------------;這主要是因為Oracle檢查發(fā)現(xiàn)數(shù)據(jù)庫設置的字符集與客戶端配置字符集不同,它將對數(shù)據(jù)進行字符集的轉換。數(shù)據(jù)庫中實際存放的數(shù)據(jù)為182(10110110)、171(10101011)、177(10110001)、177(10110001),由于數(shù)據(jù)庫字符集設置為US7ASCII,它是一個7bit的字符集,存儲在8bit的字節(jié)中,則Oracle忽略各字節(jié)的最高bit,則182(10110110)就變成了54(0110110),在ZHS16GBK中代表數(shù)字符號“6”(當然在其它字符集中也是“6”),同樣過程也發(fā)生在其它3個字節(jié),這樣“東北”就變成了“6+11”。實驗結果分析三 quote: --------------------------------------------------------------------------------最初由 tellin 發(fā)布用ZHS16GBK插入數(shù)據(jù)SQL> INSERT INTO TEST VALUES('東北');1 row created.SQL> SELECT * FROM TEST;R1--------------------6+11??SQL> EXIT--------------------------------------------------------------------------------當客戶端字符集設置為ZHS16GBK后向數(shù)據(jù)庫插入“東北”,Oracle檢查發(fā)現(xiàn)數(shù)據(jù)庫設置的字符集為US7ASCII與客戶端不一致,需要進行轉換,但字符集ZHS16GBK中的“東北”兩字在US7ASCII中沒有對應的字符,所以Oracle用統(tǒng)一的“替換字符”插入數(shù)據(jù)庫,在這里為“?”,編碼為63(00111111),這時,輸入的信息實際上已經(jīng)丟失,不管字符集設置如何改變(如下面引用的實驗結果),第二行SELECT出來的結果也都是兩個“?”號(注重是2個,而不是4個)。 quote: --------------------------------------------------------------------------------更改客戶端字符集為US7ASCII D:>SET NLS_LANG=AMERICAN_AMERICA.US7ASCIID:>SQLPLUS '/ AS SYSDBA'無法顯示用ZHS16GBK插入的字符集,但可以顯示用US7ASCII插入的字符集SQL> SELECT * FROM TEST;R1----------東北??更改服務器字符集為ZHS16GBKSQL> update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';1 row updated.SQL> COMMIT;更改客戶端字符集為ZHS16GBKD:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBKD:>SQLPLUS '/ AS SYSDBA'可以顯示以前US7ASCII的字符集,但無法顯示用ZHS16GBK插入的數(shù)據(jù),說明用ZHS16GBK插入的數(shù)據(jù)為亂碼。SQL> SELECT * FROM TEST;R1--------------------東北??--------------------------------------------------------------------------------需要指出的是,通過“update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';”來修改數(shù)據(jù)庫字符集是非常規(guī)作法,很可能引起問題,在這里只是原文引用網(wǎng)友的實驗結果。 ;實驗結果分析四 quote: --------------------------------------------------------------------------------SQL> INSERT INTO TEST VALUES('東北');1 row created.SQL> SELECT * FROM TEST;R1--------------------東北??東北SQL> EXIT--------------------------------------------------------------------------------由于此時數(shù)據(jù)庫與客戶端的字符集設置均為ZHS16GBK,所以不會發(fā)生字符集的轉換,第一行與第三行數(shù)據(jù)顯示正確,而第二行由于存儲的數(shù)據(jù)就是63(00111111),所以顯示的是“?”號。quote: --------------------------------------------------------------------------------更改客戶端字符集為US7ASCIID:>SET NLS_LANG=AMERICAN_AMERICA.US7ASCIID:>SQLPLUS '/ AS SYSDBA'無法顯示數(shù)據(jù)SQL> SELECT * FROM TEST;R1----------??????疑問2:第一行數(shù)據(jù)是用US7ASCII環(huán)境插入的,為何無法正常顯示? --------------------------------------------------------------------------------將客戶端字符集設置改為US7ASCII后進行SELECT,Oracle檢查發(fā)現(xiàn)數(shù)據(jù)庫設置的字符集為ZHS16GBK,數(shù)據(jù)需要進行字符集轉換,而第一行與第三行的漢字“東”與“北”在客戶端字符集US7ASCII中沒有對應字符,所以轉換為“替換字符”(“?”),而第二行數(shù)據(jù)在數(shù)據(jù)庫中存的本來就是兩個“?”號,所以雖然在客戶端顯示的三行都是兩個“?”號,但在數(shù)據(jù)庫中存儲的內容卻是不同的。實驗結果分析五 quote: --------------------------------------------------------------------------------SQL> INSERT INTO TEST VALUES('東北');1 row created.SQL> EXIT更改客戶端字符集為ZHS16GBKD:>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBKD:>SQLPLUS '/ AS SYSDBA'無法顯示用US7ASCII插入的字符集,但可以顯示用ZHS16GBK插入的字符集SQL> SELECT * FROM TEST;R1--------------------東北??東北6+11SQL>疑問3:US7ASCII為ZHS16GBK的子集,為何在US7ASCII環(huán)境下插入的數(shù)據(jù)無法顯示? [/B] --------------------------------------------------------------------------------在客戶端字符集設置為US7ASCII時,向字符集為ZHS16GBK的數(shù)據(jù)庫中插入“東北”,需要進行字符轉換,“東北”的ZHS16GBK編碼為182(10110110)、171(10101011)與177(10110001)、177(10110001),由于US7ASCII為7bit編碼,Oracle將這兩個漢字當作四個字符,并忽略各字節(jié)的最高位,從而存入數(shù)據(jù)庫的編碼就變成了54(00110110)、43(00101011)與49(00110001)、49(00110001),也就是“6+11”,原始信息被改變了。這時,將客戶端字符集設置為ZHS16GBK再進行SELECT,數(shù)據(jù)庫中的信息不需要改變傳到客戶端,第一、三行由于存入的信息沒有改變能顯示“東北”,而第二、四行由于插入數(shù)據(jù)時信息改變,所以不能顯示原有信息了。;分析了這么多的內容,但實際上總結起來也很簡單,要想在字符集方面少些錯誤與麻煩,需要堅持兩條基本原則: 在數(shù)據(jù)庫端:選擇需要的字符集(通過create database中的CHARACTER SET與NATIONAL CHARACTER SET子句指定);在客戶端:設置操作系統(tǒng)實際使用的字符集(通過環(huán)境變量NLS_LANG設置)。例如:CHARACTER SET ZHS16GBKNATIONAL CHARACTER SET AL16UTF16
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
91九色精品| 亚洲v天堂v手机在线| 国产精品中文字幕亚洲欧美| 亚洲网址在线观看| 日本亚洲欧洲无免费码在线| 日本va欧美va欧美va精品| 久久精品av麻豆的观看方式| 日韩欧美激情电影| 国产日韩欧美一区在线| 欧美黑人做爰爽爽爽| 国产精品亲子伦av一区二区三区 | 国产专区精品| 91亚洲一区| 99热精品久久| 免费人成黄页网站在线一区二区| 视频一区日韩| 美女久久99| 亚洲国产福利| 国产视频一区欧美| 国产精品视频一区视频二区| 欧美国产小视频| 尤物在线精品| 日韩福利视频导航| 97国产精品| 日韩专区视频网站| 老司机精品视频在线播放| 亚洲www啪成人一区二区| 伊人精品在线| 国产剧情一区二区在线观看| 性欧美videohd高精| 免费的成人av| 成人午夜在线| 国产精品人人爽人人做我的可爱| 国产日韩一区| 亚州av乱码久久精品蜜桃| 久久国产人妖系列| 蜜桃视频欧美| 麻豆一区二区三| 免费日韩视频| 国产欧美一区二区三区精品酒店| 男人的天堂久久精品| 精品99在线| 亚洲三级在线| 伊人精品一区| 狠狠久久伊人| 婷婷亚洲成人| 免费国产自久久久久三四区久久| 欧美日韩午夜| 国产精品色网| 欧美成人基地 | 免费日韩成人| 中文日韩在线| 福利一区二区三区视频在线观看| 亚洲三级在线| 亚洲经典在线| 日韩国产欧美| 美女视频黄久久| 欧美天堂在线| 国产精品美女| 久久久夜夜夜| 精品一区二区三区免费看| 免费亚洲一区| 日韩精品视频在线看| 欧美天堂亚洲电影院在线观看| 久久av免费| 日韩高清电影一区| 久久国产福利| 黄色av日韩| 久久久久亚洲| 樱桃视频成人在线观看| 国产精品久久久久久妇女| 在线日韩成人| 丝袜美腿成人在线| 91精品国产福利在线观看麻豆| 精品精品99| 国产精品扒开腿做爽爽爽软件| 亚州av日韩av| 亚洲精品一区二区在线播放∴| 91精品99| 欧美日韩少妇| 美女久久久久| 欧美女激情福利| 免费黄色成人| 神马午夜久久| 播放一区二区| 91tv亚洲精品香蕉国产一区| 中文字幕高清在线播放| 91欧美在线| 九九久久国产| 欧美xxxx中国| 精品捆绑调教一区二区三区| 伊人久久av| 极品av在线| 成人在线网站| 午夜国产精品视频| 西西人体一区二区| 免费精品视频在线| 日韩av一区二区三区| 国产日韩1区| 精品网站aaa| 97精品中文字幕| 亚洲伦乱视频| 极品日韩av| 欧美精品羞羞答答| 国产手机视频一区二区 | 久久久噜噜噜| 五月天久久777| 麻豆9191精品国产| 日韩激情一区二区| 国产精品久久久久久久久免费高清 | 久久av偷拍| 国产成人免费精品| 神马午夜在线视频| 亚洲午夜精品久久久久久app| 亚洲激情av| 日本午夜精品| 色欧美自拍视频| 日韩视频二区| 欧美午夜网站| 婷婷综合六月| 一区二区三区网站| 欧美激情网址| 久久中文字幕av| 亚洲精品成a人ⅴ香蕉片| 国产麻豆精品| 日韩在线二区| 蜜臀av性久久久久蜜臀aⅴ流畅| 青青草91久久久久久久久| 国产一区二区三区四区大秀| 国产99精品| 日本天堂一区| 欧美成a人免费观看久久| 亚洲另类黄色| 高清在线一区| 国产视频一区在线观看一区免费| 日韩av资源网| 久久精品亚洲人成影院| 亚洲欧美日韩国产一区| 久久99精品久久久久久园产越南| 999精品一区| 亚洲人成网站在线在线观看| 国产黄色精品| 国产二区精品| 国产亚洲精品美女久久久久久久久久| 精品三级久久久| 久热综合在线亚洲精品| 精品久久国产一区| 日韩中文字幕av电影| 精品亚洲自拍| 亚洲免费一区三区| 日韩一区二区三区在线免费观看| 蜜臀av在线播放一区二区三区| 欧美韩日一区| 欧美日韩一区自拍| 不卡视频在线| 免费视频一区二区三区在线观看| 国产精品毛片| 日韩精品2区| 欧美日韩亚洲一区| 另类av一区二区| 成人看片网站| 麻豆精品新av中文字幕| 免费在线看一区| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 国产精品三级| 先锋影音久久久| 国产一区二区三区网| 亚洲+小说+欧美+激情+另类| 99精品国产一区二区三区| 国产欧美亚洲一区| 在线视频亚洲| 日本少妇一区| 国产一区二区三区网| 日韩av一区二区在线影视| 尹人成人综合网| 视频二区不卡| 激情综合婷婷| 麻豆精品视频在线观看| 91亚洲无吗| 亚洲永久精品唐人导航网址| 91精品国产调教在线观看| 精品亚洲免a| 国产精品啊v在线| 91精品国产经典在线观看| 日韩在线观看一区二区| 91精品国产乱码久久久久久久| 精品一区二区三区四区五区| 国产日韩在线观看视频| 亚洲v天堂v手机在线| 国产视频一区在线观看一区免费| 亚洲成人av观看| 首页国产精品| 国产成人久久精品麻豆二区| 欧美激情 亚洲a∨综合| 国产日韩欧美| 久久狠狠久久| 久久国产精品免费精品3p| 午夜电影一区| 五月国产精品| 五月亚洲婷婷 |