如何使用enum資料型別?

KunlunDB發表於2022-01-20

在做資料庫設計時,我們經常需要給很多表增加一個‘型別’ 欄位,比如人的性別有‘男’, ‘女’,學校的型別有‘幼兒園’,‘小學’,‘中學’,‘大學’,汽車的型別有‘轎車’,‘suv’,‘mpv’等, 這種欄位的本質特點是它們包含 “有限個離散值”。


對於這種欄位,使用enum資料型別是最合適的,mysql和PostgreSQL都有此資料型別。 enum型別有這麼一些特點:


1、 在表中enum欄位儲存的實際是其順序值(整數),而不是字串。


2、 按照enum值做查詢和比較的時候,按照順序值來查詢和比較,而不是按照enum項的字串。不過mysql在這個方面有個問題(見下文截圖):與其某個enum項相同的字串做範圍比較(>, <, >=, <=)時候,並沒有按照順序值比較,而是按照字面值比較了。但是mysql在按照enum列做排序的時候,卻也能夠正確滴按照enum項的順序值來排序。


3、 postgresql的enum型別需要預先定義好,然後在create table的時候使用該型別。這樣做的好處是多個表可以使用同一個enum型別,不必多次定義而導致不一致等問題。


4、 可以對enum列定義索引,索引key排序也是按照enum順序值排序,並且索引key也是enum順序值(整數)。

 

下面的截圖是使用崑崙分散式資料庫做的示例 。裡面mysql的示例是使用崑崙分散式資料庫的儲存節點(mysql8.0.15)做的。


如何使用enum資料型別?

建立使用enum資料型別的表,然後插入資料。


如何使用enum資料型別?

對enum型別的列做範圍查詢和等值查詢,順序值決定enum項的大小關係。


如何使用enum資料型別?

按照enum型別的列排序時候,會按照其順序值而不是字面字串 做排序。查詢後設資料表可以看到enum型別的後設資料。


如何使用enum資料型別?

mysql的enum用法:可以做等值查詢,但是範圍查詢沒有按照順序值而是按照enum項的 字面字串 來比較的,這樣做其實是錯誤的。


如何使用enum資料型別?

mysql中enum列的定義,按照 enum項 出現的順序給每個enum項賦予 順序值,從0開始。


如何使用enum資料型別?

按照enum列排序時,是按照enum項 的 順序值來排序的。從後設資料字典可以看到‘職級’這個enum型別的enum項的順序值。


如何使用enum資料型別?

插入更多行後,再次排序,仍然是按照enum列的順序值而不是字面字串 來排序的。


如何使用enum資料型別?

mysql對enum列也是按照順序值排序,但是與enum字串做大小比較時候無法聰明滴按照順序值來比較。


在舉例說明enum的用法之後,我列舉一下不使用enum的資料庫設計當中不好的設計方案。這些方案應該被摒棄,切不可模仿。


1、 有人直接使用字串型別,比如varchar(N) 型別的列,來儲存這樣的欄位值,這樣的問題是,有可能上層應用的錯誤會輸入意外的欄位值,比如上例中學校型別欄位,如果應用層資料處理不充分,導致插入一行Rx.type = ‘大 學’,那麼這樣的行Rx也完全可以插入到表中。於是當你查詢 型別=‘大學’ 的行時候,就找不到Rx了。還有一個問題是空間利用率問題。在mysql和postgresql中,enum欄位實際儲存的是enum值的數值,通常會比儲存字串節省空間,而且在查詢和比較時,數值比較也比字串比較更快。


2、 另有人會在db的表中使用數字來代表型別,然後在應用層完成數字與型別字串的轉換。比如上例學校型別中,用1代表‘幼兒園’,2代表‘小學’等,然後在應用層完整這種數字與字串之間的轉換,向終端使用者展示字串,向db的對應欄位中存入數字。這樣做的問題是,增加了應用層開發的工作量和維護開銷。設想後期需要增加更多型別值,還要修改應用層程式碼。而且,沒有應用層程式碼,還完全無法理解欄位值的意義(當然,可以增加註釋說明),影響資料的可讀性。


從這裡可以看出enum型別的幾個優點:


1、 資料校驗,拒絕非法值。


2、 高效儲存和計算。


3、 資料可讀性強,不需要依賴應用程式碼來解釋。


4、 不需要應用程式做任何數值解釋和轉換,降低應用軟體開發和維護的成本。


所以,強烈建議資料庫設計和應用系統設計的時候,適當的時候使用enum型別。


-END-


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011764/viewspace-2853161/,如需轉載,請註明出處,否則將追究法律責任。

相關文章