2013-04-11 3 views
1

У меня есть два 2008 таблицы SQL Server: расписания (родителя) и ScheduleResults (ребенок)Невозможно создать Вместо Trigger

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 [email protected] AND IsEndOfRun=1 

    IF @IsEORSum=0 
    BEGIN 
      -- There are no EndOfRun results. Schedule should be active 
      UPDATE Schedules SET Status='ACT' WHERE [email protected] 
    END 
    ELSE 
    BEGIN 
      -- There is at least 1 record with IsEndOfRun=True. Schedule should be DEACTIVATED 
      UPDATE Schedules SET Status='DEA' WHERE [email protected] 
    END 

После вставки отлично работает. После обновления работает отлично. После удаления не работает. С этим сообщением появляется предупреждение:

Невозможно создать INSTEAD OF DELETE TRIGGER. Это связано с тем, что таблица имеет внешний ключ с каскадным удалением.

Мое первоначальное определение действительно имело предложение ВКЛЮЧИТЬ УДАЛЕНИЕ КАСКАДА в столбце ScheduleID. Я удалил его, но не успел. Кроме того, как вы видите, я создаю триггер AFTER, а не триггер INSTEAD. Итак, теперь мой вопрос ... Как настроить Trigger и/или FK Constraint, чтобы я мог позаботиться о ссылочной целостности и позаботиться о сценариях удаления детей?

Я ценю любую помощь от всех мастеров SQL Server.

+3

Примечание стороны: видя это заявление 'Select @ ScheduleID = ScheduleID FROM inserted', кажется, что вы думаете, что триггер будет вызываться один раз для каждой строки - это ** не ** дело; триггер будет вызываться ** один раз за оператор **, и если этот оператор влияет на несколько строк, псевдо-таблица «Inserted» будет содержать ** несколько строк **. Вы должны написать свой код запуска таким образом, чтобы он мог обрабатывать несколько строк в 'Inserted' - ваш код в настоящее время не может этого сделать. –

+0

Вам действительно нужно ** хранить ** этот статус? - похоже, было бы просто вычислить его во время извлечения (вы могли бы создать представление, содержащее логику, если хотите) –

+1

А также в дополнение к комментарию marc_s - не 'COUNT()', когда все вы хотите сделать, это установить существование или нет. 'EXISTS()' существует по какой-либо причине. –

ответ

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 
Смежные вопросы