0

テーブルの(タイプの)列CreatedDateと列に入力するために、このトリガーを使用しています。LastUpdateddatetime

CREATE TRIGGER trCreatedDate ON [LasMTest]
FOR INSERT 
AS
    UPDATE [LasMTest] 
    SET [LasMTest].Created = getdate(),
        [LasMTest].LastModified = getdate()
    FROM [LasMTest] 
    INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID]
GO

表を確認すると、日付がほんの一瞬ずれています。

Created LastModified    ID
2013-03-19 09:24:32.920 2013-03-19 09:24:32.930 4
2013-03-19 09:26:39.890 2013-03-19 09:26:39.900 5

両方が正確な時間になるようにトリガーを変更するにはどうすればよいですか?

4

3 に答える 3

2

問題を引き起こしているのは、 2 つのトリガーの相互作用です。

代わりに、両方の列をデフォルトに設定してトリガーgetdate()を破棄すると、動作するはずです。insertINSERTUPDATE

別の方法は、トリガーを、ではなく実行するINSERTトリガーとして作成することです (したがって、トリガーの起動も回避します)。INSTEAD OFINSERTUPDATEUPDATE


INSTEAD OFトリガーとして書きたい場合は、次のようになります。

CREATE TRIGGER trCreatedDate ON [LasMTest]
INSTEAD OF INSERT 
AS
    INSERT INTO LasMTest (/* Column List */,Created,LastModified)
    SELECT /* Column List */,getdate(),getdate() from inserted
GO

INSERTトリガー内のトリガー テーブルに s を挿入してINSTEAD OFも (ありがたいことに) トリガーが再帰的に起動されることはありません。IDが列の場合IDENTITY、上記の列リストに表示されます (まだ生成されていません)。

于 2013-03-19T09:40:59.513 に答える
0

これを試して:

CREATE TRIGGER trCreatedDate ON [LasMTest]

FOR INSERT 

AS
Declare @CurrentDate Datetime
Set @CurrentDate=getdate()
UPDATE [LasMTest] SET [LasMTest].Created=@CurrentDate,[LasMTest].LastModified=@CurrentDate

FROM [LasMTest] INNER JOIN Inserted ON [LasMTest].[ID]= Inserted.[ID]

GO
于 2013-03-19T09:35:52.090 に答える
0

基本的に、INSERT から更新を行うときは、UPDATE トリガーを避けたいと考えています。これはネストされたトリガーと呼ばれます。簡単な解決策の 1 つはCONTEXT_INFO()、ネストされた UPDATE トリガー コードに、既に INSERT トリガーにあることを伝えて、それ自体を抑制することです。

CREATE TRIGGER trCreatedDate ON [LasMTest]
FOR INSERT 
AS
    SET CONTEXT_INFO 0xDEADBEEF;
    UPDATE [LasMTest] 
    SET [LasMTest].Created = getdate(),
        [LasMTest].LastModified = getdate()
    FROM [LasMTest] 
    INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID];
    SET CONTEXT_INFO NULL;
GO

CREATE TRIGGER trModifiedDate ON [LasMTest]
FOR UPDATE
AS
    DECLARE @context varbinary(128);
    SET @context = CONTEXT_INFO();
    IF @context is NULL
    BEGIN
       UPDATE [LasMTest] 
          SET [LasMTest].LastModified = getdate()
        FROM [LasMTest] 
        INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID];
    END
GO

しかし、そのようなアプローチは脆弱です。例外により、context_info が設定されたままになり、セッション内の後続のすべての UPDATE トリガーが抑制される可能性があります。これには、TRY/CATCH ブロックを追加する必要があります。また、アプリケーションが独自のCONTEXT_INFO目的で使用し、スキームを台無しにするリスクが常にあります。

もう 1 つの解決策は、UPDATE トリガーをスマートにすることです。UPDATEトリガーの内部をチェックし、列が変更されたUPDATE(Created)場合はアクションを抑制できます。Created列を更新する唯一の場所Createdは INSERT トリガーであることがわかっているため、これは慣例に従って機能します。

CREATE TRIGGER trModifiedDate ON [LasMTest]
FOR UPDATE
AS
    IF NOT UPDATE(Created)
    BEGIN
       UPDATE [LasMTest] 
          SET [LasMTest].LastModified = getdate()
        FROM [LasMTest] 
        INNER JOIN Inserted ON [LasMTest].[ID] = Inserted.[ID];
    END
GO
于 2013-03-19T09:58:57.973 に答える