2009-04-17 183 views
18

如何在不支持枚舉的數據庫中實現枚舉字段? (即SQLite)如何處理數據庫中沒有枚舉字段的枚舉?

這些字段需要用「field =?」輕鬆搜索。所以使用任何類型的數據序列化都不是一個好主意。

+0

如果這是重複的,請保持好心情。在我詢問之前,我確實在StackOverflow上尋找了答案。 – epochwolf 2009-04-17 16:47:20

回答

49

使用外鍵到查找表是我使用的方法。事實上,即使我使用支持ENUM的數據庫(例如MySQL),我也會使用它。

爲了簡單起見,我可以跳過查找表中不斷出現的「id」,只是使用我在主表中需要的實際值作爲查找表的主鍵。這樣你就不需要進行連接來獲得價值。

CREATE TABLE BugStatus (
    status   VARCHAR(20) PRIMARY KEY 
); 

INSERT INTO BugStatus (status) VALUES ('NEW'), ('OPEN'), ('FIXED'); 

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL DEFAULT 'NEW', 
    FOREIGN KEY (status) REFERENCES BugStatus(status) 
); 

誠然,存儲字符串需要更多的空間比MySQL的執行ENUM,但除非有問題的表有數百萬行,這並不重要。

查找表的其它優點是,你可以添加或用一個簡單的INSERTDELETE從列表中刪除一個值,而與ENUM你必須使用ALTER TABLE重新定義列表。

也嘗試查詢ENUM中允許值的當前列表,例如在用戶界面中填充選取列表。這是一個主要的煩惱!通過查找表,很容易:SELECT status from BugStatus

如果需要(例如標記僅供管理員使用的選項),還可以將其他屬性列添加到查找表中。在ENUM中,您不能註釋條目;他們只是簡單的價值觀。

除了查找表的另一種選擇是使用CHECK約束(提供數據庫支持他們 - MySQL不):

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL 
    CHECK (status IN ('NEW', 'OPEN', 'FIXED')) 
); 

但這使用CHECK約束來自同一患有缺點如ENUM:很難更改值列表而不使用ALTER TABLE,難以查詢允許值列表,難以註釋值。

PS:SQL中的相等比較運算符是單個=。雙重==在SQL中沒有意義。

+0

感謝=對比==的東西:)直到我使用SQL已經有一段時間了。 – epochwolf 2009-04-17 23:20:02

+0

很好的答案,從我+1。 – Brann 2009-04-18 07:25:06

-1

我會使用一個varchar。這不適合你嗎?

+0

使用VARCHAR會導致非規格化的數據。如果要更改枚舉值的名稱,它需要在整個表上進行更新,而不僅僅是更改參考表中的單個行。 – 2009-04-17 17:23:18

1

你基本上有兩種選擇:

  • 使用整型字段

  • 使用VARCHAR場

我個人主張用VARCHAR處理的,因爲你不會如果你改變你的enum +這些字段是人類可讀的,但是int也有一些專業知識,也就是性能(數據的大小是一個明顯的例子),所以不會破壞任何東西

2

要限制可能的值,我將使用外鍵來保存枚舉項目的表。

如果你不想加入去做你的搜索,那麼把鍵設爲varchar如果JOINS不是問題,那麼將鍵設爲INT並且不加入,除非你需要在該字段上搜索。

請注意,將枚舉放入數據庫將排除編譯時檢查代碼中的值(除非在代碼中複製枚舉)。我發現這是一個很大的缺陷。

0

這是我最近

在我的休眠映射POJO-我不停的成員作爲字符串類型,它是VARCHAR在數據庫中。

這種情況的發生二傳手枚舉 還有一個二傳手這需要與字符串但這是私人(或如果這就是你喜歡什麼,你可以映射場兩個直。)

現在其實我使用字符串從所有封裝。對於其他應用程序 - 我的域對象使用枚舉。 就數據庫而言,我正在使用String。

如果我錯過了你的問題,我很抱歉。