sql >> Database >  >> RDS >> Sqlserver

TSQL:niet-boolean type gespecificeerde fout bij gebruik van update in een trigger

Als u alleen wijzigingen van afzonderlijke kolommen in uw trigger wilt loggen, kunt u proberen de draaiing ongedaan te maken, mogelijk in combinatie met volledige join. Het idee is dat je beide inserted en deleted voeg ze vervolgens toe aan de sleutel van de tabel en de kolom met de niet-gedraaide namen, waarbij de rijen worden uitgefilterd waar de waarden hetzelfde zijn.

Hier is een voorbeeld van de methode.

Eerst de tabeldefinities:

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()
);

Vervolgens een trigger voor het loggen van wijzigingen. Deze vangt alle bewerkingen op:invoegen, bijwerken en verwijderen:

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

Laten we nu de testtabel vullen met wat gegevens:

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

Hier is de inhoud vóór de daaropvolgende wijzigingen:

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

En laten we nu enkele wijzigingen aan de inhoud aanbrengen:

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;

Dit is wat we hebben in TestTable daarna:

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

En dit is wat er is gelogd:

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

De opstelling is natuurlijk enigszins vereenvoudigd. In het bijzonder zijn alle kolommen van de hoofdtabel die moeten worden gelogd van hetzelfde type, en het is dus niet nodig om gegevens naar een of ander generiek type te converteren om verschillende soorten gegevens te omvatten. Maar misschien is dat net wat je nodig hebt. En zo niet, dan denk ik dat dit een goed begin kan zijn voor het implementeren van de ultieme oplossing.




  1. MySQL-query met meerdere LIMIETEN

  2. TSQL DATUMTIJD ISO 8601

  3. Hoe sorteer ik een mysql-kolom met gegevens in Bytes KB MB GB?

  4. Deling van gehele getallen geeft 0