web-dev-qa-db-fra.com

Comment ajouter une colonne "dernière modification" et "créée" dans une table SQL Server?

Je conçois un nouveau schéma de base de données pour une base de données SQL Server 2012.

Chaque table doit avoir deux colonnes supplémentaires appelées modified et created qui doivent être automatiquement modifiées dès qu'une ligne est insérée ou mise à jour.

Je ne sais pas comment faire le meilleur moyen d'y arriver.

Je suppose que ce déclencheur est le meilleur moyen de le gérer.

J'essayais de trouver des exemples avec des déclencheurs .. mais les tutoriels que j'ai trouvés inséraient des données dans une autre table, etc. 

J'ai supposé que c'était un scénario assez courant mais je n'ai pas encore trouvé de réponse.

26
stevo

La colonne created est simple: il s'agit simplement d'une colonne DATETIME2(3) avec une contrainte par défaut qui est définie lors de l'insertion d'une nouvelle ligne:

Created DATETIME2(3) 
   CONSTRAINT DF_YourTable_Created DEFAULT (SYSDATETIME())

Ainsi, lorsque vous insérez une ligne dans YourTable et que vous ne spécifiez pas de valeur pour Created, elle sera définie sur la date et l'heure actuelles.

La modified représente un peu plus de travail, car vous devez écrire un déclencheur pour le cas AFTER UPDATE et le mettre à jour - vous ne pouvez pas indiquer de manière déclarative à SQL Server de le faire pour vous ....

Modified DATETIME2(3)

et alors

CREATE TRIGGER updateModified
ON dbo.YourTable
AFTER UPDATE 
AS
   UPDATE dbo.YourTable
   SET modified = SYSDATETIME()
   FROM Inserted i
   WHERE dbo.YourTable.PrimaryKey = i.PrimaryKey

Vous devez rejoindre la pseudo table Inserted qui contient toutes les lignes qui ont été mises à jour avec votre table de base sur votre clé primaire pour cette table.

Et vous devrez créer ce déclencheur AFTER UPDATE pour chaque table dans laquelle vous souhaitez placer une colonne modified.

34
marc_s

Généralement, vous pouvez avoir les colonnes suivantes:

  • LastModifiedBy
  • LastModifiedOn
  • Créé par
  • Créé sur

LastModifiedBy et CreatedBy sont des références à une table users (UserID) et les colonnes LastModifiedOn et CreatetOn sont des colonnes de date et d'heure.

Vous avez les options suivantes:

  1. Solution sans déclencheurs - J'ai lu quelque part que "Le meilleur moyen d'écrire des déclencheurs est de ne pas écrire de tels." Et vous devriez savoir qu'en général, ils nuisent à la performance. Donc, si vous pouvez les éviter, il est préférable de le faire, même utiliser des déclencheurs peut sembler la chose la plus facile à faire dans certains cas.

    Donc, éditez simplement toutes vos instructions INSERT et UPDATE pour inclure la UserID actuelle et la date et l'heure actuelles. Si un tel user ID ne peut pas être défini (utilisateur anonyme), vous pouvez utiliser 0 à la place et la valeur par défaut des colonnes (si aucun user ID n'est spécifié, ce sera NULL). Lorsque vous voyez les valeurs NULL insérées, vous devez rechercher les déclarations "coupables" et les modifier.

  2. Solution avec déclencheurs - vous pouvez créer le déclencheur AFTER INSERT, UPDATE et y renseigner les colonnes des utilisateurs. Il est facile d'obtenir la date et l'heure actuelles dans le contexte du déclencheur (utilisez GETUTCDATE() par exemple). Le problème ici est que les déclencheurs ne permettent pas de transmettre/accepter des paramètres. Donc, comme vous n'insérez pas la valeur user ID et que vous ne pouvez pas la transmettre au déclencheur. Comment trouver l'utilisateur actuel? 

    Vous pouvez utiliser SET CONTEXT_INFO et CONTEXT_INFO . Avant toutes vos instructions insert et update, vous devez utiliser le SET CONTEXT_INFO pour ajouter le current user ID au contexte actuel. Dans le déclencheur, vous utilisez la fonction CONTEXT_INFO pour l'extraire.

Ainsi, lorsque vous utilisez des déclencheurs, vous devez à nouveau éditer toutes vos clauses INSERT et UPDATE - c'est pourquoi je préfère ne pas les utiliser.

Quoi qu'il en soit, si vous n'avez besoin que de colonnes de date et d'heure et non créées/modifiées par des colonnes, l'utilisation de déclencheurs est plus durable et plus simple, car vous n'éditerez aucune autre instruction maintenant et dans le futur.


Avec SQL Server 2016, nous pouvons maintenant utiliser la fonction SESSION_CONTEXT pour lire les détails de la session. Les détails sont définis avec sp_set_session_context (sous la forme read-only ou read and write). Les choses sont un peu conviviales:

EXEC sp_set_session_context 'user_id', 4;  
SELECT SESSION_CONTEXT(N'user_id');  

Un Nice exemple .

8
gotqn

Attention, ci-dessus fonctionne bien mais pas dans tous les cas, .__ J'ai perdu beaucoup de temps et j'ai trouvé ceci utile:

create TRIGGER yourtable_update_insert
ON yourtable
AFTER UPDATE 
as
begin
   set nocount on;
   update yourtable set modified=getdate(), modifiedby = suser_sname()
   from  yourtable t 
   inner join inserted i on t.uniqueid=i.uniqueid 
end
go

set nocount on; est nécessaire sinon vous obtenez l'erreur:


Microsoft SQL Server Management Studio


Aucune ligne n'a été mise à jour.

Les données de la ligne 5 n'ont pas été validées . Source de l'erreur: Microsoft.SqlServer.Management.DataTools . Message d'erreur: Les valeurs de ligne mises à jour ou supprimées ne rendent pas la ligne unique ou modifient plusieurs lignes (2 rangées).

Corrigez les erreurs et réessayez ou appuyez sur ÉCHAP pour annuler les modifications. 


OK aide 


1
pietervnk