Oracle資料庫中字串相關字段型別辨析

2021-07-31 03:11:43 字數 4221 閱讀 3177

字串型別的字段在各關聯式資料庫中均占有重要地位。比如oracle資料庫中用於儲存字串型別資料的字段型別就超過了5種。遺憾的是,在日常工作中筆者發現很多開發者對這些型別並沒有完整的認識,更不用說設計表結構時正確的選擇字段型別了。本文將辨析oracle資料庫中表示字串的各欄位型別以及設計表結構時欄位型別的選擇依據。

oracle資料庫中,用於表示字串型別的字段型別包括char、varchar2、varchar、nchar、nvarchar2、clob和nclob等幾種,下面我們來一一介紹這些型別。

2.1 char

char型別用於儲存定長的字串,字段長度的取值範圍是1到2000位元組,預設為1位元組。因為char是定長的,所以,當儲存的字串小於設定的字段長度時,oracle將在字串尾填充空格佔位。比如我們定義了乙個字段「test_char char(2)」,而插入的記錄對應字段值為「a」,則從表中讀取的記錄的對應欄位是填充了乙個空格的「a 」。

對於char型別值的比較,oracle會在填充空格補齊到設定長度後進行。比如對於上例,當檢索條件為「where test_char=』a』」時是可以得到記錄「a 」的。

另外,在定義char的長度時可以使用單位名稱byte或char,預設為byte。即「test_char char(2 byte)」意為長度為2個位元組的char,而「test_char char(2 char)」意為長度為2個字元的char。

這裡說的「位元組」是儲存字段資訊所占用的物理儲存空間,而「字元」則是指儲存的資訊的最小邏輯單位。當資料庫使用單位元組字符集時,乙個字元的儲存空間就是乙個位元組,而當資料庫使用多位元組字符集時,乙個字元的儲存空間可能是1到n個位元組。

2.2 varchar2

varchar2型別用於儲存變長的字串,字段長度的取值範圍是1到4000位元組。varchar2是變長的,這意味著實際儲存長度與具體的字串有關。

對於varchar2型別的比較,oracle不會預先填充空格,而是直接比較值。比如我們定義乙個字段「test_varchar2 varchar2(2)」,插入對應字段值為「a 」的記錄。當檢索條件為「where test_ varchar2=』a』」時是無法得到記錄「a 」的。

另外,與char一樣,在定義varchar2型別欄位的最大長度時可以使用單位名稱byte或char,預設為byte。即「test_ varchar2 varchar2(2 byte)」意為最大長度為2個位元組的varchar2,而「test_ varchar2 varchar2 (2 char)」意為長度為2個字元的varchar2。

2.3 varchar

在oracle中,varchar被定義為varchar2的別名,其一切行為、特徵與varchar2相同。據傳,起初,oracle預留了varchar欄位型別用於與其他資料庫相容。而時至今日,它仍作為varchar2的別名存在,其意義恐怕只是對oracle資料庫自身的向下相容了。

2.4 nchar

nvarchar2型別用於儲存變長的unicode字串,其特性參見varchar2和nchar,恕不贅述。

2.6 clob

clob型別用於儲存最大不超過128tb的變長字串。clob支援事務,但不支援跨事務和會話的定位。下面的示例定義了乙個叫做clob_test的clob型別的字段:clob_test clob。

因為clob型別的字段在表中記錄的是實際資訊的指標,因此無法在sql語句中使用比較運算子。如果我們需要查詢clob_test值為「a」的記錄可以使用查詢條件「where dbms_lob.compare(t.clob_test,』a』)=0」。

2.7 nclob

nclob型別用於儲存最大不超過128tb的unicode變長字串。nclob的其他特性與clob相同,恕不贅述。

既然oracle資料庫提供了多種字段型別用於字串型別資料的儲存,那麼我們在設計資料庫表結構時應該如何選擇呢?筆者認為應該從各欄位型別的區別、限制入手,抓住字串型別資料的關鍵特性,從而選擇出最適合的字段型別。下面將逐一介紹這些關鍵特性。

3.1 最大長度

從儲存資訊的角度來說,字段支援的字串長度是資訊能否被完整保留的重要條件。char和nchar的最大長度是2000位元組,varchar2和nvarchar2的最大長度是4000位元組,clob和nclob的最大長度是128tb。當我們要選擇乙個字段型別來儲存字串資訊時,應當首先根據業務模型判斷字串的最大值,排除掉無法滿足最大儲存需求的字段型別。因為clob(nclob)型別使用時的諸多不便,當char(nchar)和varchar2(nvarchar)字段型別的最大長度限制可以滿足業務需求時,通常不使用clob(nclob)型別。

3.2 是否定長

char(nchar)型別與varchar2(nvarchar2)型別最大的區別在於是否定長。char(nchar)型別是定長的,這意味著它擁有更高的訪問效率。但是,當實際儲存的資訊小於設定的字段長度時,oracle會用空格來填充,此時會浪費一定的儲存空間。雖然對於單條記錄這個影響可以忽略不計,但對於海量記錄,這個浪費就需要引起足夠的重視了。

varchar2(nvarchar2)的情形與char(nchar)剛好相反。它通過犧牲訪問效率獲得了更高的空間利用率。

3.3 儲存內容包含的字元

nchar、nvarchar2、nclob型別儲存unicode字串,僅支援al16utf16或utf8字符集。雖然實際工作中很少遇到,但如果要儲存的字元超出al16utf16和utf8字符集範圍,那就無法使用nchar、nvarchar2、nclob等字段型別了。

3.4 是否需要建立索引

如果需要為儲存字串的字段建立索引,那麼我們要格外注意其對字段型別的限制。在clob和nclob型別的字段上是不能建立普通索引的。而在nclob型別的字段上是不能建立文字索引(如context)的。

3.5 是否可能出現資料庫遷移

如果可以預見在將來資料庫可能發生遷移,那麼設計資料庫表結構時應該充分考慮字段型別的相容性。比如,將oracle中的nchar型別遷移到ibm db2時,就需要通過ccsid子句建立相容unicode字符集的char或varchar。

第3節中從技術角度討論了儲存字串型別資料時的選擇依據,屬於設計表結構時的一些指導原則。本節將以工作指導書的形式介紹在工作中經常涉及的幾個業務場景中的字段型別選擇及原因,幫助讀者更深刻的理解各欄位型別的差異。

4.1 記錄狀態及可列舉值

在資料庫設計中,我們常常需要表示記錄狀態的字段。比如,用「r」表示記錄已發布,「o」表示記錄被檢出;再比如用「o」表示樹節點已展開,用「c」表示樹節點已關閉;甚至表示布林,用「1」表示真,用「0」表示假。

這類場景儲存的字串具有定長(或最大長度可知)、可列舉、資訊通常為英文本母或數字、經常作為檢索過濾條件等特點。

對於這類場景,我們通常使用char型別字段進行儲存。

4.2 guid、uuid與md5

guid和uuid是我們經常使用的全域性唯一識別符號。它們具有長度、格式統一,字元可列舉(16進製制數字)的特點。相應的,用於校驗的md5、sh-11、crc等也有類似的特徵。

對於這類字串,我們通常使用char型別欄位來儲存。

4.3 單據號、證件號

業務系統中經常需要儲存符合一定格式的單據號、證件號。它們除了具有定長、字元可列舉的特點外,還是一些資訊的編碼集合。以身份證為例,18位數字中就包含了戶籍位址、出生日期、性別、校驗碼等資訊。因此,它們通常會被用於建立文字索引或函式索引。

對於單據號、證件號型別的字串,我們通常使用char型別欄位來儲存。

4.4 普通字串

對於諸如「產品型號」、「產品規格」等一般業務屬性字串,通常符合變長、長度不超過4000位元組的特徵。

因此,我們可以使用varchar2來儲存這個型別的字串。

4.5 靜態頁面、大文字

在一些web專案中,我們會將靜態頁面檔案儲存在資料庫表中。一些基於諸如freemarker等模版引擎的專案也會將模版檔案儲存於資料庫表中。另外,一些類似論壇、部落格、新聞功能的應用也存在儲存大量字串的需求。

對於以上型別的需求,用排除法可知,能夠幾乎不受長度限制進行大文字儲存的型別只有clob和nclob。當然,依前所述,我更傾向於使用clob。

Oracle資料庫連線字串

oracle資料庫連線字串 經典大全 附件官方文件 2008 11 21 13 34 odbc 新版本driver server myserveraddress uid myusername pwd mypassword 舊版本driver connectstring oracleserver.wo...

Oracle資料庫中的字串函式

最近學了一些關於oracle的字串處理的方法,在這裡記下來。表示零或多個字元 表示乙個字元 對於特殊符號可使用 escape 識別符號來查詢 select from emp where ename like escape 上面的 escape 表示 後面的那個符號不當成特殊字元處理,就是查詢普通的 ...

資料庫連線字串 Oracle 連線字串

odbc 新版本driver server myserveraddress uid myusername pwd mypassword 舊版本driver connectstring oracleserver.world uid myusername pwd mypassword ole db,ol...