2017-06-08 13 views
0

Ich habe viele Felder in einer Tabelle und ich versuche, jedes Einfügen - Update - Löschen in einer anderen Tabelle zu überprüfen.Wie bekomme ich alten Wert und neuen Wert mit SQL-Trigger?

Ich habe gerade ein Problem, den Wert des genauen Feldes, das ich gewählt habe, zu erhalten.

Ich habe diesen Code geschrieben und erwarte den alten und neuen Wert eines exakten Feldes.

DECLARE @ColName NVARCHAR(225) , 
     @FieldID INT; 
    DECLARE columnCursor CURSOR 
    FOR 
     SELECT COLUMN_NAME 
     FROM INFORMATION_SCHEMA.COLUMNS 
     WHERE TABLE_NAME = 'acc_Account' 
       AND TABLE_SCHEMA = 'dbo'; 

    DECLARE @deleted_colmn INT; 

    DECLARE CurDB CURSOR 
    FOR 
     SELECT @deleted_colmn 
     FROM #Deleted; 


    OPEN columnCursor; 

    FETCH NEXT FROM columnCursor INTO @ColName; 

    WHILE (@@FETCH_STATUS <> -1) 
     BEGIN 



      --OPEN CurDB; 
      --FETCH NEXT FROM CurDB INTO @deleted_colmn; 

      SET @FieldID = (SELECT TOP 1 
            FieldID 
          FROM fld_Field 
          WHERE fld_Field.FieldName = @ColName 
          ); 


      SET @newvalue = (SELECT TOP 1 
             @ColName 
           FROM  Inserted 
           WHERE  @ColName = @ColName 
          ); 
      SET @oldvalue = (SELECT TOP 1 
             @ColName 
           FROM  Deleted 
       IF @newvalue <> @oldvalue 
       BEGIN 

        INSERT INTO dbo.utl_Audit_Trail_Field 
          (AuditTrailID , 
           FieldID , 
           OldValue , 
           NewValue , 
           CreatedDate , 
           CreatedUserID , 
           UpdatedDate , 
           UpdatedUserID 
          ) 
        VALUES (@AuditTrailID , -- AuditTrailID - bigint 
           @FieldID , -- FieldID - bigint 
           @oldvalue , -- OldValue - nvarchar(1000) 
           @newvalue , -- NewValue - nvarchar(1000) 
           @CreatedDate , -- CreatedDate - datetime 
           @CreatedUserID , -- CreatedUserID - bigint 
           @CreatedDate , -- UpdatedDate - datetime 
           @CreatedUserID -- UpdatedUserID - bigint 
          ); 

       END; 

      FETCH NEXT FROM columnCursor INTO @ColName; 

     END;    WHERE  @ColName = @ColName 

          ); 
+4

[lesen erste Dokumentation über gelöscht und eingefügt] (https://docs.microsoft.com/en-us/sql/relational-databases/triggers/use-the-inserted-and-deleted-tables) Hoffe das hilft! –

+1

@BogdanSahlean sie hören nicht auf, mich in allen Tutorials zu erwähnen, ich bin ein ziemlich gutes Beispiel. ;-) –

+1

Niemals jemals (und ich meine EVER) benutze einen Cursor in einem Trigger. Je. Dies ist eine gute Möglichkeit, ein ansonsten vollkommen gesundes RDBMS schreiend in die Knie zu zwingen und um Gnade zu flehen. –

Antwort

1

Überdenken Sie Ihre Architektur. Der Versuch, Änderungen in einer Tabelle einzeln zu erkennen und diese einzeln zu speichern, ist ein Rezept für eine Katastrophe.

Speichern Sie den gesamten Inhalt der Deleted-Tabelle in Ihrer Audit-Tabelle und stellen Sie dann sicher, dass Sie die Tabelle komprimieren, um den Platzbedarf für eine große Anzahl von Duplikaten zu reduzieren.

Plattenspeicherplatz ist billig, CPU-Leistung ist nicht.

Bearbeiten: Lesen Sie Ihren Kommentar, dass Sie die Architektur nicht ändern können; Ich würde sagen, dass Sie müssen, weil die Alternative ist, einen Auslöser so zu haben, der große Probleme verursachen wird, wenn dieser Tisch sogar entfernt stark benutzt wird. Selbst einzelne Inserts außerhalb eines Cursors werden dich so sehr verletzen, dass du dir wünschst, du wärst nie geboren worden. Für jede ms der Trigger läuft, steigt das Risiko von Sperrkonkurrenz (oder noch schlimmer, Deadlocks) exponentiell.

Verwandte Themen