Транзакция закончилась в триггере. Пакет был прерван. Производный атрибут - PullRequest
2 голосов
/ 05 сентября 2011

У меня есть этот триггер:

CREATE trigger [dbo].[DeriveTheAge] on [dbo].[Student]
after insert,update
as
begin
    declare @sid as int;
    declare @sdate as date;
    select @sid= [Student ID] from inserted;
    select @sdate=[Date of Birth] from inserted;
    commit TRANSACTION
    if(@sdate is not null)
    begin
        update Student set Age=DATEDIFF(YEAR,@sdate,GETDATE()) where [Student ID]=@sid;
    end
    print 'Successfully Done'
end

Как и предполагалось, триггер автоматически вычисляет производный атрибут «Возраст» по дате рождения.Но я получаю эту ошибку, когда выполняю вставку:

(1 row(s) affected)
Successfully Done
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

Изначально я избегал этой ошибки, потому что строки обновлялись, несмотря на ошибку.Но теперь, когда я вставляю запись из FORNT END, запись не обновляется.Вместо этого он выдает это исключение: enter image description here

Кто-нибудь может мне помочь?

Кстати, у меня есть SQL Server 2008 R2 и Visual Studio 2010.

ИСПРАВЛЕНИЕ : Записи все еще обновляются.Но исключением является Вилан.

Обновление

CREATE TRIGGER [dbo].[DeriveTheAge] 
ON [dbo].[Student]
FOR INSERT, UPDATE
AS
BEGIN
    UPDATE s 
      SET Age = DATEDIFF(YEAR, [Date of Birth], CURRENT_TIMESTAMP)
      FROM dbo.Student AS s
      INNER JOIN inserted AS i
      ON s.[Student ID] = i.[Student ID]
      WHERE i.[Date of Birth] IS NOT NULL;
      commit transaction
END
GO

1 Ответ

8 голосов
/ 05 сентября 2011

Почему вы делаете в триггере? Почему вы не обрабатываете многострочные вставки или обновления? Вы не можете просто объявить переменные и назначить их из вставленных - как вы думаете, какие значения будут назначены при обновлении 2, 15 или 6000 строк?

CREATE TRIGGER [dbo].[DeriveTheAge] 
ON [dbo].[Student]
FOR INSERT, UPDATE
AS
BEGIN
    UPDATE s 
      SET Age = DATEDIFF(YEAR, [Date of Birth], CURRENT_TIMESTAMP)
      FROM dbo.Student AS s
      INNER JOIN inserted AS i
      ON s.[Student ID] = i.[Student ID]
      WHERE i.[Date of Birth] IS NOT NULL;
END
GO

Все это говорит о том, зачем вам нужен триггер для расчета чьего-либо возраста? Вы можете получить это по дате рождения прямо сейчас во время запроса и знать, что это будет точно, в отличие от этого устаревшего значения, которое вы сохранили в таблице. Обратите внимание, что если их строка не обновляется более года, возраст, указанный в таблице, устарел. Когда вы вернетесь и обновите возраст для всех строк в таблице? Один раз в день? Все, что меньше, и ваша колонка Age совершенно ненадежна и бессмысленна.

Кроме того, DATEDIFF(YEAR не является надежным способом подсчета возраста в первую очередь. Все, что он делает, это подсчитывает количество пройденных границ года, он не знает, является ли фактический день рождения человека 1 января или 31 декабря или где-то между ними.

Наконец, я бы не стал печатать с триггера. Кто будет использовать этот оператор печати, когда вы не будете отлаживать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...