2015-02-05 73 views
0

我有以下簡單的DB:SQL規則取決於所選值

Table Types: 
- ID int 
- TypeName nvarchar 

Table Users: 
- ID int 
- UserName nvarchar 
- TypeID int 

Table BusyTime 
- ID int 
- UserID int 
- BTime time(0) 

但有限制 - 在空閒時間的記錄應該是僅適用於用戶,其中有TYPEID = 3.用戶使用的typeid = 1,並用TYPEID = 2在BusyTime中不能有記錄(它與業務邏輯矛盾) 如何在MS SQL級別上對其進行描述?或者我應該重新設計數據庫?

+0

觸發器可用於確保數據的一致性。 – jarlh 2015-02-05 15:34:50

回答

2

我假設在每個表的主鍵是剛上ID。你需要改變什麼,添加一個UNIQUE KEY約束上IDTypeIDUsers

ALTER TABLE Users ADD CONSTRAINT UQ_User_Types_XRef (ID,TypeID) 

並創建BusyTime表:

CREATE TABLE BusyTime (
    ID int not null, 
    UserID int not null, 
    BTime time(0) not null, 
    _Type_XRef as 3 persisted, 
    constraint PK_BusyTime PRIMARY KEY (ID), 
    constraint FK_BusyTime_Users FOREIGN KEY (UserID) 
     references Users (ID), 
    constraint FK_BusyTime_Users_XRef FOREIGN KEY (UserID,_Type_XRef) 
     references Users (ID,TypeID) 
) 

在那裏我已經假定PK_BusyTimeFK_BusyTime_Users是你現有的限制。 FK_BusyTime_Users(這是「真正的」外鍵約束),現在FK_BusyTime_Users_XRef存在,這是一個品味問題。

+0

不錯,然後你創建一個日常使用的視圖,隱藏需要使fk成爲可能的虛擬列。 – jarlh 2015-02-05 15:40:08

0

您可以使用檢查約束來禁止無效類型: https://technet.microsoft.com/en-us/library/ms188258%28v=sql.105%29.aspx

+0

檢查約束是否適用於多表跨越檢查? – jarlh 2015-02-05 15:31:22

+0

是的,你基本上定義了一個可以查詢不同表格的函數。您可以使用MSDN示例 – Lee 2015-02-05 15:35:05

+1

但是您仍然需要在'Users'表上實現一個觸發器,以防止'TypeID'從3更改爲其他*,如果*該用戶在'BusyTime'中有任何行。 – 2015-02-05 15:36:20

0

設置這樣的條件約束是可能的。一種方法是複合索引添加到users

create unique index idx_users(type, id) on users(type, id) 

然後使用一個外鍵約束:

alter table busytime add _type as (3) persisted not null; 
alter table busytime add constraint foreign key (_type, userId) on users(type, id); 

不幸的是,我認爲是必要的persisted此列,因此它實際上是在佔用空間記錄。

不幸的是,我不認爲這個工程之一:

alter table busytime add constraint foreign key (3, userId) on users(type, id);