sql >> Database teknologi >  >> RDS >> Sqlserver

TSQL:ikke-boolesk type specificeret fejl ved brug af opdatering i en trigger

Hvis du blot ønsker at logge ændringer af individuelle kolonner i din trigger, kan du prøve at unpivot, eventuelt i forbindelse med fuld join. Ideen er, at du deaktiverer begge inserted og deleted sæt dem derefter sammen på tabellens nøgle og kolonnen, der indeholder de ikke-pivotede navne, og filtrer de rækker fra, hvor værdierne er de samme.

Her er et eksempel på en illustration af metoden.

Først tabeldefinitionerne:

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

Dernæst en trigger til logføring af ændringer. Denne vil fange alle handlingerne:indsæt, opdater og slet:

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
 

Lad os nu udfylde testtabellen med nogle data:

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

Her er indholdet før de efterfølgende ændringer:

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

Og lad os nu foretage nogle ændringer af indholdet:

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;
 

Her er, hvad vi har i TestTable bagefter:

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

Og dette er, hvad der er blevet logget:

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
 

Opsætningen er selvfølgelig blevet noget forenklet. Især alle hovedtabellens kolonner, der skal logges, er af samme type, og det er derfor ikke nødvendigt at konvertere data til en generisk type for at omfatte forskellige slags data. Men måske er det lige hvad du har brug for. Og hvis ikke, tror jeg, at dette kan give en god start på implementeringen af ​​den ultimative løsning.




  1. Sum php-array (oprettet ud fra mysql-resultater) afhængigt af mysql-værdier i en anden mysql-kolonne

  2. Sådan tilføjes et BEGRÆNSNINGSNAVN til en allerede EKSISTERENDE BEGRÆNSNING

  3. postgresql distinct virker ikke

  4. Forespørg en MySQL-database og grupper efter datointerval for at oprette et diagram