我有一张名为' tblDive'列:
create table tblDive (
DiveNumber int
InstructorNumber int
ClubNumber int
InstructorSigniture date
)
和另一张表:
create table tblWorksAt (
InstructorNumber int
ClubNumber int
StartWorkingDate date
EndWorkingDate date
)
表' tblWorksAt'有这个记录:
InstructorNumber | ClubNumber | StartWorkingDate | EndWorkingDate
1 2 1.1.2000 1.1.2005
我想创建一个触发器来检查插入新潜水的时间,如果教练在登录潜水的同时真的在这个俱乐部工作。 例如,如果我插入新的潜水:
insert into tblDive (DiveNumber InstructorNumber ClubNumber InstructorSigniture)
values 111, 1, 2, 1.1.2009
我无法插入此记录,因为1号教练在2005年1月1日停止在2号俱乐部工作
答案 0 :(得分:1)
使用触发器的替代方法是使用检查约束和用户定义的函数。
在正确的时间,在正确的俱乐部使用检查是指导员的功能:
CREATE FUNCTION CheckEmployment(@InstructorNumber int, @ClubNumber int, @checkdate date)
RETURNS int
AS
BEGIN
DECLARE @retval int
SELECT @retval = COUNT(*)
FROM tblWorksAt
WHERE InstructorNumber = @InstructorNumber
AND ClubNumber = @ClubNumber
AND (EndWorkingDate IS NULL OR EndWorkingDate > @checkdate)
RETURN @retval
END;
GO
使用它的检查约束:
ALTER TABLE tblDive
ADD CONSTRAINT chkEmployed
CHECK (dbo.CheckEmployment(InstructorNumber, ClubNumber, InstructorSigniture) != 0);
这可能不是最有效的方法,但它应该完成工作。函数中的逻辑也可能需要改进,我可能错过了一些东西。
Sample SQL Fiddle显示它的实际效果。
答案 1 :(得分:0)
我要做的是给你一些提示和不太明显的关于可能帮助你编写触发器的触发器的信息,但你需要写它。
inserted
表格
在SQL Server触发器中,您可以引用2个伪表:inserted
和deleted
表。名字有点欺骗,特别是如果你正在做UPDATE
。要记住的是,在引擎盖下,UPDATE
是一个删除加插入。
基本上,inserted
是新的(或更新的)行,deleted
是在应用更改之前从UPDATE删除的行和/或前一行。
对于直接INSERT
语句,deleted
表应该为空。
因此,您希望在inserted
中查找符合某组条件的行。有两种合理的方法可以解决这个问题:
<强>加入强>
如果您加入inserted
到tblWorksAt
,您现在拥有了所需的所有数据。这样的事情可以加入表并查找通过业务规则的行:
select 1
from inserted i
inner join tblWorksAt wa on wa.InstructorNumber = i.InstructorNumber and i.ClubNumber = wa.ClubNumber
where i.InstructorSignature between wa.StartWorkingDate and wa.EndWorkingDate
如何处理查询
就像我之前说过的那样:
要检查所有行是否都符合该条件,您可以:
inserted
中没有连接的总行数。inserted
中的每一行循环,我现在会告诉你,在触发器中几乎不是一个好主意。要检查至少有一行是否未能通过标准,您可以:
between
更改为not between
,并围绕if (exists(...))
包装此查询。inner join
更改为left outer join
,将where子句移动到连接,然后添加一个显示tblWorksAt.InstructorNumber is null
的新WHERE子句,然后围绕if (exists(...))
包装此查询投掷错误
现在您知道如何查找通过或失败的行。现在您只需要抛出一个错误来防止语句完成并阻止数据持久化。我将把它作为练习留给你。它应该很容易研究。