Sql server 如何创建多表检查约束?
请想象一下这个小数据库 图解 删除了死ImageShack链接-志愿者数据库关系图 桌子 联想 志愿者可以报名参加多项活动。Sql server 如何创建多表检查约束?,sql-server,check-constraints,Sql Server,Check Constraints,请想象一下这个小数据库 图解 删除了死ImageShack链接-志愿者数据库关系图 桌子 联想 志愿者可以报名参加多项活动。 活动可能由多名志愿者组成 一个事件可能有多个班次。 移位只属于单个事件 一个班次只能有一名志愿者。 志愿者可以轮班工作 检查约束 我可以创建一个检查约束吗 强制要求没有轮班人员 一个没有报名参加的志愿者 那个转变是什么 我可以创建一个检查约束吗 强制执行两个重叠的班次 他们的员工从来都不是同一个人 志愿者 有一种方法是使用触发器,我不推荐这样做。我建议不要将业务逻辑放在数
活动可能由多名志愿者组成 一个事件可能有多个班次。
移位只属于单个事件 一个班次只能有一名志愿者。
志愿者可以轮班工作 检查约束
有一种方法是使用触发器,我不推荐这样做。我建议不要将业务逻辑放在数据库级别。db不需要知道是谁,在什么时候安排了某个班次。这种逻辑应该放在您的业务层中。我建议使用存储库构建模式。Scott gutherie在他的mvc 1.0书中有一个非常好的章节描述了这一点(下面的链接)
加强数据完整性的最佳场所是数据库。请放心,如果您允许的话,一些开发人员,不管是有意还是无意,都会找到一种方法将不一致的内容潜入数据库 下面是一个带有检查约束的示例:
CREATE FUNCTION dbo.SignupMismatches()
RETURNS int
AS BEGIN RETURN (
SELECT count(*)
FROM Shift s
LEFT JOIN EventVolunteer ev
ON ev.EventId = s.EventId
AND ev.VolunteerId = s.VolunteerId
WHERE ev.Id is null
) END
go
ALTER TABLE Shift ADD CONSTRAINT chkSignup CHECK (dbo.SignupMismatches() = 0);
go
CREATE FUNCTION dbo.OverlapMismatches()
RETURNS int
AS BEGIN RETURN (
SELECT count(*)
FROM Shift a
JOIN Shift b
ON a.id <> b.id
AND a.Start < b.[End]
AND a.[End] > b.Start
AND a.VolunteerId = b.VolunteerId
) END
go
ALTER TABLE Shift ADD CONSTRAINT chkOverlap CHECK (dbo.OverlapMismatches() = 0);
以下是表格定义:
set nocount on
if OBJECT_ID('Shift') is not null
drop table Shift
if OBJECT_ID('EventVolunteer') is not null
drop table EventVolunteer
if OBJECT_ID('Volunteer') is not null
drop table Volunteer
if OBJECT_ID('Event') is not null
drop table Event
if OBJECT_ID('SignupMismatches') is not null
drop function SignupMismatches
if OBJECT_ID('OverlapMismatches') is not null
drop function OverlapMismatches
create table Volunteer (
id int identity primary key
, name varchar(50)
)
create table Event (
Id int identity primary key
, name varchar(50)
)
create table Shift (
Id int identity primary key
, VolunteerId int foreign key references Volunteer(id)
, EventId int foreign key references Event(id)
, Description varchar(250)
, Start datetime
, [End] datetime
)
create table EventVolunteer (
Id int identity primary key
, VolunteerId int foreign key references Volunteer(id)
, EventId int foreign key references Event(id)
, Location varchar(250)
, [Day] datetime
, Description varchar(250)
)
我要做的是在event志愿者表上有一个自动递增的Identity列,在EventId、志愿者id对上有一个唯一的约束。使用EventID(标识)作为移位表的外键。这将非常简单地强制执行您想要的约束,同时在某种程度上规范化您的数据 我知道这不是你一般问题的答案,但是我认为这是解决你具体问题的最好办法 编辑:
我本应该把这个问题通读一遍的。此解决方案将防止一名志愿者在同一活动中轮班,即使他们没有重叠。也许将轮班开始和结束时间移动到EventVoluntain并在该表上设置时间检查约束就足够了,尽管这样轮班表之外就有了轮班数据,这听起来并不直观。问题1很简单。只要让您的轮班表直接引用EventVoluntive表,您就可以了Hmm。我认为这是一个数据完整性问题,而不是业务逻辑。我是否还需要一个从EventVoluntive表中删除行的约束条件<代码>更改表事件志愿者添加约束chkSignup2检查(dbo.SignupMismatches()=0)代码>或者,这不是必须的吗?@Zack:那很容易测试;我的猜测是,如果允许删除,第二个约束是必要的。作为一种最佳实践,完全不允许删除:最好使用位标志“过时”。也可以查看Josh的评论,它也可以处理删除操作。读者可能希望在走这条路线之前查看一下。请注意使用函数强制执行这样的检查约束!t-sql并不总是在update语句后检查函数,允许绕过约束。图已经消失(来自ImageShack)。有可能更新吗?
insert into Volunteer (name) values ('Dubya')
insert into Event (name) values ('Build Wall Around Texas')
-- Dubya tries to build a wall, but Fails because he's not signed up
insert into Shift (VolunteerID, EventID, Description, Start, [End])
values (1, 1, 'Dunbya Builds Wall', '2010-01-01', '2010-01-02')
-- Properly signed up? Good
insert into EventVolunteer (VolunteerID, EventID)
values (1, 1)
insert into Shift (VolunteerID, EventID, Description, Start, [End])
values (1, 1, 'Dunbya Builds Wall', '2010-01-01', '2010-01-03')
-- Fails, you can't start the 2nd wall before you finished the 1st
insert into Shift (VolunteerID, EventID, Description, Start, [End])
values (1, 1, 'Dunbya Builds Second Wall', '2010-01-02', '2010-01-03')
set nocount on
if OBJECT_ID('Shift') is not null
drop table Shift
if OBJECT_ID('EventVolunteer') is not null
drop table EventVolunteer
if OBJECT_ID('Volunteer') is not null
drop table Volunteer
if OBJECT_ID('Event') is not null
drop table Event
if OBJECT_ID('SignupMismatches') is not null
drop function SignupMismatches
if OBJECT_ID('OverlapMismatches') is not null
drop function OverlapMismatches
create table Volunteer (
id int identity primary key
, name varchar(50)
)
create table Event (
Id int identity primary key
, name varchar(50)
)
create table Shift (
Id int identity primary key
, VolunteerId int foreign key references Volunteer(id)
, EventId int foreign key references Event(id)
, Description varchar(250)
, Start datetime
, [End] datetime
)
create table EventVolunteer (
Id int identity primary key
, VolunteerId int foreign key references Volunteer(id)
, EventId int foreign key references Event(id)
, Location varchar(250)
, [Day] datetime
, Description varchar(250)
)