Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何创建多表检查约束?_Sql Server_Check Constraints - Fatal编程技术网

Sql server 如何创建多表检查约束?

Sql server 如何创建多表检查约束?,sql-server,check-constraints,Sql Server,Check Constraints,请想象一下这个小数据库 图解 删除了死ImageShack链接-志愿者数据库关系图 桌子 联想 志愿者可以报名参加多项活动。 活动可能由多名志愿者组成 一个事件可能有多个班次。 移位只属于单个事件 一个班次只能有一名志愿者。 志愿者可以轮班工作 检查约束 我可以创建一个检查约束吗 强制要求没有轮班人员 一个没有报名参加的志愿者 那个转变是什么 我可以创建一个检查约束吗 强制执行两个重叠的班次 他们的员工从来都不是同一个人 志愿者 有一种方法是使用触发器,我不推荐这样做。我建议不要将业务逻辑放在数

请想象一下这个小数据库

图解 删除了死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)
    )