在程式中列舉(enum)是一種常見的資料型別,會定義一些常數,限制資料只能是這些常數中的其中一個,方便表達狀態,避免無意義的數字。
以 C# 為例:
在程式中要表達狀態就可以使用 OrderStatus 這個列舉來表達,非常容易閱讀:
但是在 Sql Server 中並沒有列舉(enum)可以使用,我們在儲存資料時就需要儲存「魔法數字」,例如上面的 1 代表「待處理訂單」,2 代表「訂單處理中」等等,但是我們在查詢資料時無法直接知道「3」這個數字到底代表什麼意思,也無法限制資料是否正確。
當然也可以直接儲存字串,但也一樣無法直接限制這個欄位的值,很可能會出現錯誤的參數(例如未定義的資料或是錯字),無法確認資料是否正確。
既然 SQL Server 沒有支援 enum,那我們也可以使用其他的方式解決。
如果要修改已存在的資料表也可以這樣定義:
這樣在 Orders 資料表的 Status 欄位如果出現未定義的值時就會無法新增/更新,確保資料的正確性:
註:依照不同的資料庫定續,限制的值很可能不會區分大小寫
建立用來儲存列舉的資料表:
在 OrderStatus 資料表中新增列舉內容:
建立 Orders 資料表,並且將 Status 欄位與 OrderStatus 資料表綁定外鍵約束:
這樣在新增/更新資料時如果與「列舉」內容不符,就會拋出錯誤,確保資料正確:
以 C# 為例:
public enum OrderStatus
{
Pending = 1, // 待處理訂單
Processing = 2, // 訂單處理中
Shipped = 3, // 訂單已出貨
Delivered = 4, // 訂單已送達
}
在程式中要表達狀態就可以使用 OrderStatus 這個列舉來表達,非常容易閱讀:
OrderStatus orderStatus = OrderStatus.Pending;
但是在 Sql Server 中並沒有列舉(enum)可以使用,我們在儲存資料時就需要儲存「魔法數字」,例如上面的 1 代表「待處理訂單」,2 代表「訂單處理中」等等,但是我們在查詢資料時無法直接知道「3」這個數字到底代表什麼意思,也無法限制資料是否正確。
當然也可以直接儲存字串,但也一樣無法直接限制這個欄位的值,很可能會出現錯誤的參數(例如未定義的資料或是錯字),無法確認資料是否正確。
既然 SQL Server 沒有支援 enum,那我們也可以使用其他的方式解決。
限制欄位內容
假設我們有一個最簡單的訂單資料表,有 Status 欄位來儲存資料,可以使用 CHECK 來限制對應的值只能是指定的內容:
CREATE TABLE Orders(
Id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
Status NVARCHAR(50) NOT NULL CHECK (Status IN('Pending', 'Processing', 'Shipped', 'Delivered')),
);
如果要修改已存在的資料表也可以這樣定義:
ALTER TABLE Orders ADD CONSTRAINT CHK_OrderStatus CHECK (Status IN ('Pending', 'Processing', 'Shipped', 'Delivered'));
這樣在 Orders 資料表的 Status 欄位如果出現未定義的值時就會無法新增/更新,確保資料的正確性:
[23000][547] Line 1: The UPDATE statement conflicted with the CHECK constraint "CHK_OrderStatus". The conflict occurred in database "myDb", table "dbo.Orders", column 'Status'.
註:依照不同的資料庫定續,限制的值很可能不會區分大小寫
建立資料表儲存列舉值,綁定外鍵約束
還有另一個方法,就是建立另一個資料表,用來儲存列舉對應的內容,並且透過外鍵來限制資料是否正確。建立用來儲存列舉的資料表:
CREATE TABLE OrderStatus
(
Id INT PRIMARY KEY,
Status NVARCHAR(50) NOT NULL
);
在 OrderStatus 資料表中新增列舉內容:
insert into OrderStatus (Id, Status)
values (1, N'Pending'),
(2, N'Processing'),
(3, N'Shipped'),
(4, N'Delivered');
建立 Orders 資料表,並且將 Status 欄位與 OrderStatus 資料表綁定外鍵約束:
CREATE TABLE Orders
(
Id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
Status INT NOT NULL REFERENCES OrderStatus(Id)
);
這樣在新增/更新資料時如果與「列舉」內容不符,就會拋出錯誤,確保資料正確:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Orders__Status". The conflict occurred in database "myDb", table "OrderStatus", column 'Id'.
感謝分享~
回覆刪除