2015-02-05 50 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);