0

以下は、挿入/更新アクションのためにSQLテーブルの1つで使用されるトリガーです。このトリガーは99/100回正常に機能しますが、時々次のエラーメッセージが表示されます。

列'TransactionDate'、テーブル'AgentResourcesU01.dbo.TransactionLog'に値NULLを挿入できません。列はnullを許可しません。
INSERTは失敗します。ステートメントは終了されました。

Insertステートメントからわかるように、トランザクションログテーブルの列はとTransactionDate, Operator, TableName, Action, TableStringですUserId。冒頭のSELECTステートメントで変数を設定した@transDateので、悪いデータが入ってこない限り、NULLが入ることはありません。

何かご意見は?

    BEGIN
        SELECT @symetraNumber = SymetraNumber, @lastChangeOperator = LastChangeOperator, @transDate = LastChangeDate, @entityType = EntityType, 
        @firstName = FirstName, @lastName = LastName, @suffix = NameSuffix, @corpName = CorporateName, @controlId = ControlId
        FROM inserted

        IF @firstName IS NULL SET @firstName = 'NULL'
        IF @lastName IS NULL SET @lastName = 'NULL'
        IF @suffix IS NULL SET @suffix = 'NULL'
        IF @corpName IS NULL SET @corpName = 'NULL'
        IF @controlId IS NULL SET @controlId = 'NULL'

        SET @tableString = 'SymNum:' + @symetraNumber + ' EntType:' + @entityType + ' Fname:' + @firstName + ' Lname:' + @lastname + ' Suff:' + @suffix +
            ' CorpName:' + @corpName + ' ctrlId:' + @controlId

        INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
        VALUES (@transDate, 'Op', @tableName, @action, @tableString, @lastChangeOperator)
    END
4

2 に答える 2

1

マークのポイントを示すために、これらの厄介な変数やIFチェックをすべて行わずに、セットベースの方法でこれを行うことができます。

INSERT dbo.TransactionLog
(
  TransactionDate, 
  Operator, 
  TableName, 
  Action,
  TableString,
  UserId
)
SELECT 
  LastChangeDate, 
  'Op',
  @TableName,
  @action, 
     'SymNum:'      + COALESCE(SymetraNumber, 'NULL')
     + ' EntType:'  + COALESCE(EntityType,    'NULL')
     + ' Fname:'    + COALESCE(FirstName,     'NULL')
     + ' Lname:'    + COALESCE(LastName,      'NULL')
     + ' Suff:'     + COALESCE(NameSuffix,    'NULL')
     + ' CorpName:' + COALESCE(CorporateName, 'NULL')
     + ' ctrlId:'   + COALESCE(ControlId,     'NULL'),
  LastChangeOperator
FROM inserted; 

基になるテーブルでNULL可能である場合LastChangeDateは、NOT NULLとしてマークするか、NULLが挿入される問題を修正するか、またはその両方を行います。トリガーはこの制約について知る必要はありませんが、次のようにすることで回避できます(値がNULLの場合は、今すぐに設定してください)。

...
  UserId
)
SELECT 
  COALESCE(LastChangeDate, CURRENT_TIMESTAMP), 
  'Op',
...
于 2012-09-27T19:06:21.893 に答える
0

[1] INSERT / UPDATE / DELETEトリガーがあり、誰かがベーステーブルから行を削除しようとすると、insertedトリガーからのテーブルの行はゼロになると思います。この例を見てください:

CREATE TABLE MyTableWithTrigger (
    MyID INT IDENTITY PRIMARY KEY,
    LastUpdateDate DATETIME NOT NULL
);
GO

CREATE TABLE TransactionLog (
    TransactionLogID INT IDENTITY PRIMARY KEY,
    CreateDate DATETIME NOT NULL DEFAULT GETDATE(),
    LastUpdateDate DATETIME NOT NULL,
    MyID INT NOT NULL
);
GO

CREATE TRIGGER trIUD_MyTableWithTrigger_Audit
ON MyTableWithTrigger
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    DECLARE @LastUpdateDate DATETIME, @MyID INT;
    SELECT @LastUpdateDate=i.LastUpdateDate, @MyID=i.MyID
    FROM inserted i;

    INSERT TransactionLog (LastUpdateDate, MyID)
    VALUES (@LastUpdateDate, @MyID) 
END;
GO

PRINT 'Test 1'
INSERT  MyTableWithTrigger (LastUpdateDate)
VALUES  ('2011-01-01');
DELETE MyTableWithTrigger;
SELECT * FROM MyTableWithTrigger;
SELECT * FROM TransactionLog;

出力:

Msg 515, Level 16, State 2, Procedure trIUD_MyTableWithTrigger_Audit, Line 10
Cannot insert the value NULL into column 'LastUpdateDate', table 'Test.dbo.TransactionLog'; column does not allow nulls. INSERT fails.
The statement has been terminated.

[2]トリガーを修正するには(Marcのコメントを参照)、Alex Kuznetsovの本(SQL Serverを使用した防御データベースプログラミング:AmazonRed Gate-PDF)の192〜199ページをお読みください。

于 2012-09-27T19:21:15.240 に答える