0

行の開始日から終了日までの期間である「期間」列を更新するために、テーブルにトリガーを設定しようとしています。ただし、列を挿入/更新するたびに、SCOPE_INDENTITY() が null を返し続けるため、トリガーは機能しません。どうすればこれを修正できますか?

ALTER TRIGGER [dbo].[CalcDuration]
ON [dbo].[Event]
AFTER INSERT, UPDATE, DELETE 
AS

DECLARE @STARTED datetime
DECLARE @FINISHED datetime
DECLARE @ID int

SELECT @ID = SCOPE_IDENTITY()

SELECT @STARTED  = [Date & Time Started] FROM  dbo.Event WHERE [Event ID] = @ID
SELECT @FINISHED = [Date & Time Finished] FROM dbo.Event WHERE [Event ID] = @ID

UPDATE dbo.Event 
SET Duration = DATEDIFF (  hour, @STARTED, @FINISHED )
WHERE [Event ID] = @ID
4

2 に答える 2

1

そのためにトリガーを使用することを主張する場合after(注:AFTER DELETEは必要ありません)、次のことができます

CREATE TRIGGER ai_event
ON event AFTER INSERT,UPDATE
as
BEGIN
UPDATE event 
SET  Duration  = DATEDIFF(hour, i.[Date & Time Started],i.[Date & Time Finished])
from event e 
INNER JOIN INSERTED i ON (i.id = e.id)

END;

ただし、Durationこの場合、計算された [persisted] 列を使用する方が良いオプションのようです...

ALTER TABLE event ADD Duration2 AS DATEDIFF(hour, [Date & Time Started],
[Date & Time Finished]) PERSISTED;
于 2013-07-11T15:34:11.853 に答える
1

SCOPE_INDENTITY()現在のスコープ内で最後に挿入された ID 値のみを返すため、トリガー内で使用された場合、トリガーで挿入操作が実行された後にのみ値が返されます。これはここでは当てはまらないため、NULL を返します。

テーブルINSERTEDを使用できる挿入/更新された値のIDを取得しようとしていると思います。

次に、UPDATE と INSERT は複数の行で機能する可能性があるため、トリガーが単一の行でのみ機能すると想定することは大きな間違いです。INSERTEDテーブルには、挿入/更新されたすべての行が含まれています。

したがって、トリガーは次のようになります。

UPDATE e
SET e.Duration = DATEDIFF (hour, e.[Date & Time Started], e.[Date & Time Finished])
FROM dbo.Event e
INNER JOIN INSERTED i on e.[Event ID] = i.[Event ID]

そして最後に、これは完全に不必要なトリガーの使用であることも指摘します。計算列を使用して同じことを実行できます (実行する必要があります)。したがって、列を次のように変更した場合:

ALTER TABLE  dbo.Event
ALTER COLUMN [Duration] AS DATEDIFF(hour, [Date & Time Started], [Date & Time Finished])

トリガーを必要とせずに、常に正しい期間が得られます。

于 2013-07-11T15:34:12.077 に答える