sql >> データベース >  >> RDS >> Sqlserver

TSQL:トリガーで更新を使用した非ブール型指定エラー

    トリガー内の個々の列の変更をログに記録するだけの場合は、完全結合と組み合わせて、ピボットを解除してみてください。アイデアは、両方のinsertedのピボットを解除することです およびdeleted 次に、テーブルのキーとピボットされていない名前を含む列でそれらを結合し、値が同じである行を除外します。

    これがメソッドの例です。

    まず、テーブルの定義:

    CREATE TABLE TestTable (
      ID int IDENTITY PRIMARY KEY,
      Attr1 int,
      Attr2 int,
      Attr3 int
    );
    
    CREATE TABLE TestTableLog (
      ID int IDENTITY PRIMARY KEY,
      TableID int,
      AttrName sysname,
      OldValue int,
      NewValue int,
      Timestamp datetime DEFAULT GETDATE()
    );
    

    次に、変更をログに記録するためのトリガー。これは、挿入、更新、削除のすべての操作をキャッチします:

    CREATE TRIGGER trTestTable ON TestTable
    AFTER INSERT, UPDATE, DELETE
    AS BEGIN
      WITH inserted_unpivot AS (
        SELECT
          ID,
          AttrName,
          Value
        FROM inserted i
        UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
      ),
      deleted_unpivot AS (
        SELECT
          ID,
          AttrName,
          Value
        FROM deleted d
        UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
      )
      INSERT INTO TestTableLog (TableID, AttrName, OldValue, NewValue)
      SELECT
        ISNULL(i.ID, d.ID),
        ISNULL(i.AttrName, d.AttrName),
        d.Value,
        i.Value
      FROM inserted_unpivot i
        FULL JOIN deleted_unpivot d
          ON i.ID = d.ID AND i.AttrName = d.AttrName
      WHERE CASE i.Value WHEN d.Value THEN 0 ELSE 1 END = 1
    END
    

    次に、TestTableにいくつかのデータを入力しましょう:

    WHILE (SELECT COUNT(*) FROM TestTable) < 15
      INSERT INTO TestTable
      SELECT RAND() * 1000, RAND() * 1000, RAND() * 1000
    ;
    

    その後の変更前の内容は次のとおりです。

    ID          Attr1       Attr2       Attr3
    ----------- ----------- ----------- -----------
    1           820         338         831
    2           795         881         453
    3           228         430         719
    4           36          236         105
    5           246         115         649
    6           488         657         438
    7           990         360         15
    8           668         978         724
    9           872         385         562
    10          460         396         462
    11          62          599         630
    12          145         815         439
    13          595         7           54
    14          587         85          655
    15          80          606         407
    

    それでは、コンテンツにいくつかの変更を加えましょう:

    UPDATE TestTable SET Attr2 = 35 WHERE ID = 3;
    UPDATE TestTable SET Attr3 = 0 WHERE ID BETWEEN 6 AND 10;
    INSERT INTO TestTable VALUES (1, 1, 1);
    DELETE FROM TestTable WHERE ID = 14;
    

    これがTestTableにあるものです その後:

    ID          Attr1       Attr2       Attr3
    ----------- ----------- ----------- -----------
    1           820         338         831
    2           795         881         453
    3           228         35          719
    4           36          236         105
    5           246         115         649
    6           488         657         0
    7           990         360         0
    8           668         978         0
    9           872         385         0
    10          460         396         0
    11          62          599         630
    12          145         815         439
    13          595         7           54
    15          80          606         407
    16          1           1           1
    

    そして、これがログに記録されたものです:

    ID          TableID     AttrName   OldValue    NewValue    Timestamp
    ----------- ----------- ----------- ----------- ----------- -----------------------
    1           3           Attr2       430         35          2011-08-22 20:12:19.217
    2           10          Attr3       462         0           2011-08-22 20:12:19.227
    3           9           Attr3       562         0           2011-08-22 20:12:19.227
    4           8           Attr3       724         0           2011-08-22 20:12:19.227
    5           7           Attr3       15          0           2011-08-22 20:12:19.227
    6           6           Attr3       438         0           2011-08-22 20:12:19.227
    7           16          Attr1       NULL        1           2011-08-22 20:12:19.227
    8           16          Attr3       NULL        1           2011-08-22 20:12:19.227
    9           16          Attr2       NULL        1           2011-08-22 20:12:19.227
    10          14          Attr1       587         NULL        2011-08-22 20:12:19.230
    11          14          Attr2       85          NULL        2011-08-22 20:12:19.230
    12          14          Attr3       655         NULL        2011-08-22 20:12:19.230
    

    もちろん、セットアップは多少単純化されています。特に、ログに記録されるメインテーブルの列はすべて同じタイプであるため、さまざまな種類のデータを含めるためにデータを汎用タイプに変換する必要はありません。しかし、多分それはあなたが必要とするものです。そうでない場合は、これが究極のソリューションを実装するための良いスタートを提供できると思います。




    1. 接続が失われた/切断されたトランザクションでのMySQLロールバック

    2. タイムゾーンを保存するための適切なデータ型は何ですか?

    3. Windowsでuuidを生成するpostgresql

    4. Mysql SelectRows2つの列が同じ値を持たない場合