⑴ Oracle資料庫插入日期格式字元串給date類型欄位,nls_date_format參數值作用
查詢各個級別nls_date_format
設置nls_date_format
2)其次,設定nls_date_format的值
①session級別設定值:
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'
設定之後再查詢會發現nls_session_parameters視圖中nls_date_format的值已經變了,而nls_instance_parameters、nls_database_parameters視圖中的值沒有變。
session級別——如果只是希望自己看到某種格式而不影響其他人看到的結果。
②instance級別設定值:
alter system set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'
此級別的值在oracle9i以後就不允許設定了。
③database級別設定值:
oracle不允許設定此級別的參數值,也沒有提供設定語句。
更改日期類型格式化
目的:減少客戶端對時間欄位(字元串,日期)格式化
⑵ Oracle資料庫入門之函數/類型
Oracle主要數據類型
概述 各種資料庫所支持的數據類型大同小異 與標准sql語言中的數據類型可能略有出入
類型 varchar 可以在聲明欄位時設置它的長度上限 而且使用它之後 就不必再考慮空格的存在
若插入的字元串的長度低於長度上限 系統就會自動將其縮減為字元串的真實長度
number(m n) 既可以用來表示整型 也可以表示浮點型 但m不可以超過 如果n為 或者省略n 就代表它是整數
date 用來存放日期和時間
blob 通常是在應用程序中使用到它 而不是在資料庫中利用SQL指令直接使用
比如通過JDBC技術訪問資料庫 讀寫blob或clob類型的欄位 即讀寫長的字元串信息等等
char 它是一種定長的字元類型 在Oracle資料庫不區分字元和字元串 它們被統稱為字元型或文本型
所謂定長的字元型是指 插入的字元串若沒有達到約定的欄位長度 系統就會在字元串尾部自動補空格
同樣 讀取時的欄位長度永遠是聲明時的欄位長度 而且在比較字元串內容的時候 也需要考慮到空格的過濾
nchar 它也是定長的字元串類型 它是SQL語言標准中規定的 通常採用Unicode編碼來保存不同國家或不同語言的字元
varchar SQL標准在定義varchar時並沒有保證能夠向前和向後兼容 即有可能隨著語言標準的修改而產生不兼容的問題
所以Oracle定義了同varchar型類似的varchar 型 就是為了在Oracle以後的版本中 都永遠支持varchar 類型
Oracle這么做就是為了確保此類型向前後兼容 以達到能夠在Oracle系列資料庫中進行數據的導入和導出的目的
long 它和varchar 的差別在於 它不支持對字元串內容進行檢索 即查詢時不可以對它的內容進行條件查詢
而varchar 和char nchar型等等都可以在查詢的時候直接檢索字元串的內容
補充 select * from v$nls_parameters;資料庫的配置信息以數據表的形式存在 通常稱其為關於數據的數據或數據字典
實際上它查詢的是數據字典中的一個視圖 其中NLS_CHARACTERSET對應的是當前的資料庫字元集
預設均為使用資料庫字元集 教程中使用的是安裝時默認的ZHS GBK字元集 即漢字占 個位元組 英文占 個位元組
而NLS_NCHAR_CHARACTERSET對應的是nchar或nvarchar 類型所採用的輔助字元集 即AL UTF 字元集
實際上AL UTF 是一種 位定長的Unicode編碼的字元集 而資料庫字元集以及這種國家字元集都可以修改
但資料庫字元集修改後可能會面臨很嚴重的後果 除非是資料庫管理員 普通用戶不必對這方面進行深究
資料庫中的數據導入導出的時候 如果源資料庫和目標資料庫所採用的字元集不同 也很容易出問題
函數
概述 函數可以認為是能夠完成相對獨立的功能的一段代碼的集合 Oracle函數相當於其它語言中的方法或過程
Oracle函數可以分為單行函數和多行函數兩大類 Oracle函數都是有返回值的
所謂的單行函數是針對查詢結果中的每一行都起作用 都會返回一個結果
多行函數也就是所謂分組函數 是針對一組查詢的記錄 或者說多行 返回一個結果
單行 操作數據項 接受參數並返回處理結果 對每一返回行均起作用 可修改數據類型 可嵌套使用
單行函數分為字元函數 數值函數 日期函數 轉換函數 通用函數
多行 也稱分組函數 即對一組數據進行運算 針對一組數據(多行記錄)只能返回一個結果
多行函數包括avg() count() max() min() sum()等
比如select avg(sal) max(sal) min(sal) sum(sal) max(hiredate) min(hiredate) from emp;
續一 使用Oracle的系統函數中的單行函數可實現諸多功能 如對數據進行計算 控制數據的輸出格式
設置和改變日期的顯示格式 進行數據類型轉換 使用NVL等函數處理空值 實現IF THEN ELSE多路分支邏輯等等
續二 轉換函數不會改變表中數據的欄位類型和值 它就相當於將數據復制了一份 所轉換的是復制之後的數據
數據類型轉換包括隱含轉換和顯式轉換兩種方式 建議使用顯式的數據類型轉換 確保SQL語句的可靠性
續三 通用函數適用於包括空值在內的任何類型數據 通常用來實現空值的處理 空值的過濾或設置預設值等
通用函數包括nvl() nvl () nullif() coalesce() case表達式 decode()等
嵌套 單行函數可以嵌套使用 嵌套層次無限制 分組函數最多可嵌套兩層 嵌套函數的執行順序是由內到外
單行比如select empno lpad(initcap(trim(ename)) ) 姓名 job sal from emp;
多行比如select max(avg(sal)) from emp group by deptno; 其實這里再使用分組函數就沒有意義了
說明 通常資料庫層面提供的函數 只是進行數據的簡單的處理 或者說是只能實現極為常規的功能
所以就不應該 或者說是不要指望在資料庫查詢的層面來實現特別復雜的業務邏輯
如果應用程序的邏輯跟資料庫混在一起的話 會不利於代碼的維護和更新
而且也不利於資料庫的管理 包括數據移植 資料庫導入導出等等
日期類型
概述 在計算機操作系統或者各種高級編程語言中 日期通常會被保存成一個長整數 通常記錄的是毫秒
Oracle內部以數字格式存儲日期和時間信息 世紀 年 月 日 小時 分鍾 秒
預設的日期格式是DD—MON—YY 可使用sysdata函數獲取當前系統日期和時間
運算 日期型數據可以直接加或減一個數值 結果認為日期 約定的該數值代表的是相加減的天數
兩個日期型數據可以相減 結果為二者相差多少天 二者不能 因為日期相加是沒有意義的
NVL()函數
概述 它用於將空值null替換為指定的預設值 適用於字元 數字 日期等類型數據
格式 NVL(exp exp ) 如果表達式exp 值為null 則返回exp 值 否則返回exp 值
舉例 select empno ename sal m sal+nvl(m ) from emp;
select empno ename job nvl(job No job yet ) from emp;
NVL ()函數
概述 它用於實現條件表達式功能
格式 NVL (exp exp exp ) 如果表達式exp 值不為null 則返回exp 值 否則返回exp 值
舉例 select empno ename sal m nvl (m sal+m sal) 總收入 from emp;
NULLIF()函數
概述 它用於數據等價性比較並根據比較結果返回null或其中一個被比較的數值 實際開發中應用並不是很多
格式 nullif(exp exp ) 如果表達式exp 與exp 的值相等 則返回null 否則返回exp 的值
舉例 select name 原名 nullif(pen_name name) 化名 from author;
COALESCE()函數
概述 它用於實現數據「接合」功能
格式 coalesec(exp exp ) 依次考察各參數表達式 遇到非null值即停止並返回該值
若表達式均為null值 則返回null 通常最後一個表達式都是能確保不是空值的欄位
舉例 select empno ename sal m coalesec(sal+m sal ) 總收入 from emp;
CASE表達式
概述 它用於實現多路分支結構
格式 case exp when parison_exp then return_exp
[when parison_exp then return_exp
when parison_expn then return_expn
else else_exp]
end
舉例 select empno ename sal
case deptno when then 財務部
when then 研發部
when then 銷售部
else 未知部門
end 部門
from emp;
說明 CASE中的每一個表達式(如deptno 財務部等)都可以是復合而成的
這種對齊方式的書寫是為了增加可讀性 當然也可以把代碼寫在同一行上
其中case到end之間的整體就相當於普通查詢中的一個欄位 end後面的「部門」是別名
DEDODE()函數
概述 和case表達式類似 它也用於實現多路分支結構
格式 decode(col|expression search result
[ search result ]
[ default])
舉例 select empno ename sal
decode(deptno 財務部
研發部
銷售部
未知部門 )
部門
from emp;
COUNT()函數
格式 count(*)返回組中總記錄數目
count(exp)返回表達式exp值非空的記錄
count(distinct(exp))返回表達式exp值不重復的 非空的記錄數目
舉例 select count(*) from emp; 預設的情況下 整個表就是一組
select count(m) from emp; 返回emp表中m欄位不為空的記錄(行)數目
select count(distinct(deptno)) from emp; 查找deptno值為非空且不重復的記錄數目
分組函數與空值
概述 分組函數省略列中的空值 可使用NVL()函數強制分組函數處理空值
舉例 select avg(m) from emp; 等價於sum(m)/count(m)
select sum(m) from emp; 計算表中非空的m值的總和
select avg(nvl(m )) from emp; 等價於avg(nvl(m ))/count(*)
GROUP BY子句
概述 它用於將表中數據分成若干小組
格式 select column group_function(column)
from table
[where condition]
[group by group_by_expression]
[order by column];
舉例 select deptno avg(sal) from emp group by deptno;
說明 出現在SELECT列表中的欄位 如果不是包含在組函數中 那麼該欄位必須同時在GROUP BY子句中出現
包含在GROPY BY子句中的欄位則不必須出現在SELECT列表中 子句執行順序是where→group by→order by預設按升序排列
補充 select deptno job avg(sal) from emp group by deptno job order by deptno desc; 基於多個欄位的分組
select deptno avg(sal) from emp; 非法
注意 如果沒有GROUP BY子句 SELECT列表中不允許出現欄位(單行函數)與分組函數混用的情況
WHERE中不允許使用分組函數 如select deptno avg(sal) from emp where avg(sal)> group by deptno; 非法
這跟子句執行的順序有關 where子句最先執行 在執行where子句的時候還沒有執行過group by子句
於是程序不知道這是在分組 也不曾計算過avg(sal)的組內平均工資 所以在where子句中不允許使用分組函數
由於還沒有執行過group by子句 所以此時就不確定如何怎麼分組以及分多少個組
所以where子句中只能進行初級過濾 此時可以使用HAVING子句實現對平均工資的過濾
HAVING子句
概述 它用於過濾分組
格式 select column group_function(column)
from table
[where condition]
[group by group_by_expression]
[having group_condition]
[order by column];
舉例 select deptno job avg(sal)
from emp
where hiredate >= to_date( yyyy mm dd )
group by by deptno job
having avg(sal) >
lishixin/Article/program/Oracle/201311/19087
⑶ oracle資料庫中有哪些字元集,字元集之間的子集和超集關系是怎麼樣的
理解ORACLE資料庫字元集
一.引言
ORACLE資料庫字元集,即Oracle全球化支持(Globalization Support),或即國家語言支持(NLS)其作用是用本國語言和格式來存儲、處理和檢索數據。利用全球化支持,ORACLE為用戶提供自己熟悉的資料庫母語環境,諸如日期格式、數字格式和存儲序列等。Oracle可以支持多種語言及字元集,其中oracle8i支持48種語言、76個國家地域、229種字元集,而oracle9i則支持57種語言、88個國家地域、235種字元集。由於oracle字元集種類多,且在存儲、檢索、遷移oracle數據時多個環節與字元集的設置密切相關,因此在實際的應用中,資料庫開發和管理人員經常會遇到有關oracle字元集方面的問題。本文通過以下幾個方面闡述,對oracle字元集做簡要分析
二.字元集基本知識
2.1字元集
實質就是按照一定的字元編碼方案,對一組特定的符號,分別賦予不同數值編碼的集合。Oracle資料庫最早支持的編碼方案是US7ASCII。
Oracle 的字元集命名遵循以下命名規則 :
即: <語言><比特位數><編碼 >
比如: ZHS16GBK表示採用GBK編碼格式、16位(兩個位元組)簡體中文字元集
2.2字元編碼方案
2.2.1 單位元組編碼
(1)單位元組7位字元集,可以定義128個字元,最常用的字元集為 US7ASCII
(2)單位元組8位字元集,可以定義256個字元,適合於歐洲大部分國家
例如:WE8ISO8859P1(西歐、8位、ISO標准8859P1編碼 )
2.2.2 多位元組編碼
(1)變長多位元組編碼
某些字元用一個位元組表示,其它字元用兩個或多個字元表示,變長多位元組編碼常用於對亞洲語言的支持, 例如日語、漢語、印地語等
例如:AL32UTF8(其中AL代表ALL,指適用於所有語言)、 zhs16cgb231280
(2)定長多位元組編碼
每一個字元都使用固定長度位元組的編碼方案,目前oracle唯一支持的定長多位元組編碼是AF16UTF16,也是僅用於國家字元集
2.2.3 unicode 編碼
Unicode 是一個涵蓋了目前全世界使用的所有已知字元的單一編碼方案,也就是說Unicode為每一個字元提供唯一的編碼。UTF-16是unicode的16位編碼方式,是一種定長多位元組編碼,用2個位元組表示一個unicode字元,AF16UTF16是UTF-16編碼字元集。
UTF-8 是unicode的8位編碼方式,是一種變長多位元組編碼,這種編碼可以用1、2、3個位元組表示一個unicode字元,AL32UTF8,UTF8、UTFE是UTF-8編碼字元集
2.3 字元集超級
當一種字元集(字元集A)的編碼數值包含所有另一種字元集(字元集B)的編碼數值,並且兩種字元集相同編碼數值代表相同的字元時,則字元集A是字元集B的超級,或稱字元集B是字元集A的子集。
Oracle8i 和oracle9i官方文檔資料中備有子集-超級對照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由於US7ASCII是最早的Oracle資料庫編碼格式,因此有許多字元集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
2.4 資料庫字元集(oracle伺服器端字元集)
資料庫字元集在創建資料庫時指定,在創建後通常不能更改。在創建資料庫時,可以指定字元集(CHARACTER SET)和國家字元集(NATIONAL CHARACTER SET)。
2.4.1 字元集
(1) 用來存儲CHAR, VARCHAR2, CLOB, LONG等類型數據
(2) 用來標示諸如表名、列名以及PL/SQL變數等
(3) 用來存儲SQL和PL/SQL程序單元等
2.4.2 國家字元集:
(1) 用以存儲NCHAR, NVARCHAR2, NCLOB等類型數據
(2) 國家字元集實質上是為oracle選擇的附加字元集,主要作用是為了增強oracle的字元處理能力,因為NCHAR數據類型可以提供對亞洲使用定長多位元組編碼的支持,而資料庫字元集則不能。國家字元集在oracle9i中進行了重新定義,只能在unicode編碼中的AF16UTF16和UTF8中選擇,默認值是 AF16UTF16
2.4.3查詢字元集參數
可以查詢以下數據字典或視圖查看字元集設置情況
nls_database_parameters 、props$、 v$nls_parameters
查詢結果中NLS_CHARACTERSET表示字元集,NLS_NCHAR_CHARACTERSET表示國家字元集
2.4.4 修改資料庫字元集
按照上文所說,資料庫字元集在創建後原則上不能更改。如果需要修改字元集,通常需要導出資料庫數據,重建資料庫,再導入資料庫數據的方式來轉換,或通過ALTER DATABASE CHARACTER SET語句修改字元集,但創建資料庫後修改字元集是有限制的,只有新的字元集是當前字元集的超集時才能修改資料庫字元集,例如UTF8是US7ASCII的超集,修改資料庫字元集可使用ALTER DATABASE CHARACTER SET UTF8。
2.5 客戶端字元集(NLS_LANG參數)
2.5.1 客戶端字元集含義
客戶端字元集定義了客戶端字元數據的編碼方式,任何發自或發往客戶端的字元數據均使用客戶端定義的字元集編碼,客戶端可以看作是能與資料庫直接連接的各種應用,例如sqlplus,exp/imp等。客戶端字元集是通過設置NLS_LANG參數來設定的。
2.5.2 NLS_LANG 參數格式
NLS_LANG=_.
Language: 顯示oracle消息,校驗,日期命名
Territory :指定默認日期、數字、貨幣等格式
Client character set :指定客戶端將使用的字元集
例如: NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是語言,AMERICA是地區,US7ASCII是客戶端字元集
2.5.3 客戶端字元集設置方法
1)UNIX 環境
$NLS_LANG=「simplified chinese」_china.zhs16gbk
$export NLS_LANG
編輯oracle用戶的profile文件
2)Windows 環境
編輯注冊表
Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME0
2.5.4 NLS 參數查詢
Oracle 提供若干NLS參數定製資料庫和用戶機以適應本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通過查詢以下數據字典或v$視圖查看。
NLS_DATABASE_PARAMETERS-- 顯示資料庫當前NLS參數取值,包括資料庫字元集取值
NLS_SESSION_PARAMETERS-- 顯示由NLS_LANG 設置的參數,或經過alter session 改變後的參數值(不包括由NLS_LANG 設置的客戶端字元集)
NLS_INSTANCE_PARAMETE-- 顯示由參數文件init.ora 定義的參數V$NLS_PARAMETERS--顯示資料庫當前NLS參數取值
2.5.5 修改NLS參數
使用下列方法可以修改NLS參數
(1)修改實例啟動時使用的初始化參數文件
(2)修改環境變數 NLS_LANG
(3)使用ALTER SESSION語句,在oracle會話中修改
(4)使用某些SQL函數
NLS 作用優先順序別:Sql function>alter session>環境變數或注冊表>參數文件>資料庫默認參數
三.導入/導出與字元集轉換
3.1 EXP/IMP
Export 和 Import 是一對讀寫Oracle數據的工具。Export 將 Oracle 資料庫中的數據輸出到操作系統文件中, Import 把這些文件中的數據讀到Oracle 資料庫中,由於使用exp/imp進行數據遷移時,數據從源資料庫到目標資料庫的過程中有四個環節涉及到字元集,如果這四個環節的字元集不一致,將會發生字元集轉換。
EXP
____________ _________________ _____________
|imp導入文件|<-><->
------------ ----------------- -------------
IMP
____________ _________________ _____________
|imp導入文件|->|環境變數NLS_LANG|->|資料庫字元集|
------------ ----------------- -------------
四個字元集是
(1)源資料庫字元集
(2)Export過程中用戶會話字元集(通過NLS_LANG設定)
(3)Import過程中用戶會話字元集(通過NLS_LANG設定)
(4)目標資料庫字元集
3.2導出的轉換過程
在Export過程中,如果源資料庫字元集與Export用戶會話字元集不一致,會發生字元集轉換,並在導出文件的頭部幾個位元組中存儲Export用戶會話字元集的ID號。在這個轉換過程中可能發生數據的丟失。
例:如果源資料庫使用ZHS16GBK,而Export用戶會話字元集使用US7ASCII,由於ZHS16GBK是16位字元集,而US7ASCII是7位字元集,這個轉換過程中,中文字元在US7ASCII中不能夠找到對等的字元,所以所有中文字元都會丟失而變成「?? 」形式,這樣轉換後生成的Dmp文件已經發生了數據丟失。
因此如果想正確導出源資料庫數據,則Export過程中用戶會話字元集應等於源資料庫字元集或是源資料庫字元集的超集
3.3導入的轉換過程
(1)確定導出資料庫字元集環境
通過讀取導出文件頭,可以獲得導出文件的字元集設置
(2)確定導入session的字元集,即導入Session使用的NLS_LANG環境變數
(3)IMP讀取導出文件
讀取導出文件字元集ID,和導入進程的NLS_LANG進行比較
(4)如果導出文件字元集和導入Session字元集相同,那麼在這一步驟內就不需要轉換,如果不同,就需要把數據轉換為導入Session使用的字元集。可以看出,導入數據到資料庫過程中發生兩次字元集轉換
第一次:導入文件字元集與導入Session使用的字元集之間的轉換,如果這個轉換過程不能正確完成,Import向目標資料庫的導入過程也就不能完成。
第二次:導入Session字元集與資料庫字元集之間的轉換。
然而,oracle8i的這種轉換只能在單位元組字元集之間進行,oracle8i導入Session不支持多位元組字元集之間的轉換,因此為了避免第一次轉換,導入Session使用的NLS_LANG與導出文件字元集相同,第二次轉換(通過SQL*Net)支持任何兩種字元集。以上情況在Oracle9i中略有不同
四.亂碼問題
oracle在數據存儲、遷移過程中經常發生字元亂碼問題,歸根到底是由於字元集使用不當引起。下面以使用客戶端sqlplus向資料庫插入數據和導入/導出(EXP/IMP)過程為例,說明亂碼產生的原因。
4.1使用客戶端sqlplus向資料庫存儲數據
這個過程存在3個字元集設置
(1)客戶端應用字元集
(2)客戶端NLS_LANG參數設置
(3)伺服器端資料庫字元集(Character Set)設置
客戶端應用sqlplus中能夠顯示什麼樣的字元取決於客戶端操作系統語言環境(客戶端應用字元集),但在應用中錄入這些字元後,這些字元能否在資料庫中正常存儲,還與另外兩個字元集設置緊密相關,其中客戶端NLS_LANG參數主要用於字元數據傳輸過程中的轉換判斷。常見的亂碼大致有兩種情形:
(1)漢字變成問號「?」;
當從字元集A 轉換成字元集B時,如果轉換字元之間不存在對應關系,NLS_LANG使用替代字元「?」替代無法映射的字元
(2)漢字變成未知字元(雖然有些是漢字,但與原字元含義不同)
轉換存在對應關系,但字元集A 中的字元編碼與字元集B 中的字元編碼代表不同含義
4.2發生亂碼原因
亂碼產生是由於幾個字元集之間轉換不匹配造成,分以下幾種情況:
(註:字元集之間如果不存在子集、超集對應關系時的情況不予考慮,因為這種情況下字元集之間轉換必產生亂碼)
1)伺服器端資料庫字元集與客戶端應用字元集相同,與客戶端NLS_LANG參數設置不同
如果客戶端NLS_LANG字元集是其它兩種字元集的子集,轉換過程將出現亂碼。
解決方法:將三種字元集設置成同一字元集,或NLS_LANG字元集是其它兩種字元集的超集
2 )伺服器端資料庫字元集與客戶端NLS_LANG參數設置相同,與客戶端應用字元集不同
如果客戶端應用字元集是其它兩種字元集的超集時,轉換過程將出現亂碼,但對於單位元組編碼存儲中文問題,可參看本文第5章節的分析
3 )客戶端應用字元集、客戶端NLS_LANG參數設置、伺服器端資料庫字元集互不相同
此種情況較為復雜,但三種字元集之間只要有不能轉換的字元,則必產生亂碼
4.3導入/導出過程出現亂碼原因
這個過程存在4個字元集設置,在3.1章節中已分析
(1)源資料庫字元集
(2)EXP過程中NLS_LANG參數
(3)IMP過程中NLS_LANG參數
(4)目標資料庫字元集
出現亂碼原因
1 )當源資料庫字元集不等於EXP過程中NLS_LANG參數,且源資料庫字元集是EXP過程中NLS_LANG的子集,才能保證導出文件正確,其他情況則導出文件字元亂碼
2 )EXP過程中NLS_LANG字元集不等於IMP過程中NLS_LANG字元集,且EXP過程中NLS_LANG字元集是IMP過程中NLS_LANG字元集的子級, 才能保證第一次轉換正常,否則第一次轉換中出現亂碼。
3 )如果第一次轉換正常,IMP過程中NLS_LANG字元集是目標資料庫字元集的子集或相同,才能保證第二次轉換正常,否則則第二次轉換中出現亂碼
五.單位元組編碼存儲中文問題
由於歷史的原因,早期的oracle沒有中文字元集(如oracle6、oracle7、oracle7.1),但有的用戶從那時起就使用資料庫了,並用US7ASCII字元集存儲了中文,或是有的用戶在創建資料庫時,不考慮清楚,隨意選擇一個默認的字元集,如WE8ISO8859P1或US7ASCII,而這兩個字元集都沒有漢字編碼,雖然有些時候選用這種字元集好象也能正常使用,但用這種字元集存儲漢字信息從原則上說就是錯誤的,它會給資料庫的使用與維護帶來一系列的麻煩。
正常情況下,要將漢字存入資料庫,資料庫字元集必須支持中文,而將資料庫字元集設置為US7ASCII等單位元組字元集是不合適的。US7ASCII字元集只定義了128個符號,並不支持漢字。另外,如果在SQL*PLUS中能夠輸入中文,操作系統預設應該是支持中文的,但如果在NLS_LANG中的字元集設置為US7ASCII,顯然也是不正確的,它沒有反映客戶端的實際情況。但在實際應用中漢字顯示卻是正確的,這主要是因為Oracle檢查資料庫與客戶端的字元集設置是同樣的,那麼數據在客戶與資料庫之間的存取過程中將不發生任何轉換,但是這實際上導致了資料庫標識的字元集與實際存入的內容是不相符的。而在SELECT的過程中,Oracle同樣檢查發現資料庫與客戶端的字元集設置是相同的,所以它也將存入的內容原封不動地傳送到客戶端,而客戶端操作系統識別出這是漢字編碼所以能夠正確顯示。
在這個例子中,資料庫與客戶端都沒有設置成中文字元集,但卻能正常顯示中文,從應用的角度看好象沒問題。然而這裡面卻存在著極大的隱患,比如在應用length或substr等字元串函數時,就可能得到意外的結果。
對於早期使用US7ASCII字元集資料庫的數據遷移到oracle8i/9i中(使用zhs16gbk),由於原始數據已經按照US7ASCII格式存儲,對於這種情況,可以通過使用Oracle8i的導出工具,設置導出字元集為US7ASCII,導出後使用UltraEdit等工具打開dmp文件,修改第二、三字元,修改 0001 為0354,這樣就可以將US7ASCII字元集的數據正確導入到ZHS16GBK的資料庫中。
六.結束語
為了避免在資料庫遷移過程中由於字元集不同導致的數據損失,oracle提供了字元集掃描工具(character set scanner),通過這個工具我們可以測試在數據遷移過程中由於字元集轉換可能帶來的問題,然後根據測試結果,確定數據遷移過程中最佳字元集解決方案。
參考文獻
[1]Biju Thomas , Bob Bryla 《oracle9i DBA基礎I 學習指南》電子工業出版社 2002