我有两个SQL Server 2008表:Schedules(父级)和ScheduleResults(子级)
CREATE TABLE Schedules(
ID int identity primary key NOT NULL,
Status nvarchar(3)
) [ON PRIMARY]
和
CREATE TABLE ScheduleResults(
ID int identity primary key NOT NULL,
ScheduleID int NOT NULL CONSTRAINT [FK_ScheduleResults_Schedules] REFERENCES Schedules(ID) ON DELETE CASCADE,
IsEndOfRun bit NOT NULL CONSTRAINT DF_ScheduleResults_IsEndOfRun DEFAULT(0)
) [ON PRIMARY]
逻辑是在插入/更新/删除孩子之后,我会查看父母的所有孩子。如果其中任何一个具有IsEndOfRun = 1,那么父计划记录状态将变为'DEA',否则它将变为'ACT'。如果没有找到,它仍然会进入'ACT'。
所以这是我的触发器:
CREATE TRIGGER ScheduleResultsStatus
ON [ScheduleResults] AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
DECLARE @ScheduleID int
DECLARE @IsEORSum int
SELECT @ScheduleID=ScheduleID FROM inserted
SELECT @IsEORSum=COUNT(*) FROM ScheduleResults WHERE ScheduleID=@ScheduleID AND IsEndOfRun=1
IF @IsEORSum=0
BEGIN
-- There are no EndOfRun results. Schedule should be active
UPDATE Schedules SET Status='ACT' WHERE ID=@ScheduleID
END
ELSE
BEGIN
-- There is at least 1 record with IsEndOfRun=True. Schedule should be DEACTIVATED
UPDATE Schedules SET Status='DEA' WHERE ID=@ScheduleID
END
插入后工作完美。更新后工作完美。删除后不起作用。触发器名称上出现警告,并显示以下消息:
无法创建INSTEAD OF DELETE TRIGGER。这是因为table有一个带有级联删除的外键。
我的原始定义在ScheduleID列上确实有一个ON DELETE CASCADE子句。我删除了它,但没有成功。另外,正如您所看到的,我正在创建一个AFTER触发器,而不是INSTEAD触发器。那么现在我的问题是...如何调整Trigger和/或FK约束以让我处理参照完整性并处理删除子项场景?
我感谢所有SQL Server向导的任何帮助。
答案 0 :(得分:1)
感谢之前的评论。它引发了一些想法,我不仅能够使它工作,而且代码使用集合更简单。这是后代的代码:
CREATE TRIGGER ScheduleResultsStatus
ON [ScheduleResults] AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
UPDATE Schedules SET Status='ACT' WHERE ID IN (SELECT DISTINCT Schedules.ID FROM Schedules INNER JOIN deleted ON Schedules.ID=deleted.ScheduleID)
UPDATE Schedules SET Status='DEA' WHERE ID IN (SELECT DISTINCT Schedules.ID FROM Schedules INNER JOIN inserted ON Schedules.ID=inserted.ScheduleID WHERE IsEndOfRun=1)
UPDATE Schedules SET Status='ACT' WHERE ID IN (SELECT DISTINCT Schedules.ID FROM Schedules INNER JOIN inserted ON Schedules.ID=inserted.ScheduleID Group BY Schedules.ID HAVING SUM(CONVERT(int, IsEndOfRun))=0)
GO