SQL Server Déclencheur de mise à Jour, Obtenir Uniquement les champs modifiés
Je suis conscient de COLUMNS_UPDATED
, eh bien j'ai besoin d'un raccourci rapide (si quelqu'un l'a fait, je suis déjà d'en faire un, mais si quelqu'un peut sauver mon temps, je vous remercie)
J'ai besoin fondamentalement d'un fichier XML de mise à jour des valeurs de la colonne, j'en ai besoin pour la réplication but.
SELECT * from inséré me donne chaque colonne, mais j'ai besoin que ceux mis à jour.
quelque chose comme...
CREATE TRIGGER DBCustomers_Insert
ON DBCustomers
AFTER UPDATE
AS
BEGIN
DECLARE @sql as NVARCHAR(1024);
SET @sql = 'SELECT ';
I NEED HELP FOR FOLLOWING LINE ...., I can manually write every column, but I need
an automated routin which can work regardless of column specification
for each column, if its modified append $sql = ',' + columnname...
SET @sql = $sql + ' FROM inserted FOR XML RAW';
DECLARE @x as XML;
SET @x = CAST(EXEC(@sql) AS XML);
.. use @x
END
OriginalL'auteur Akash Kava | 2009-08-10
Vous devez vous connecter pour publier un commentaire.
À l'intérieur de la gâchette, vous pouvez utiliser
COLUMNS_UPDATED()
comme cela dans le but de obtenir la valeur mise à jourMais ce snipet de code ne fonctionne pas lorsque vous avez une table avec plus de 62 colonnes.. Arth.Débordement...
Ici est la version finale qui gère plus de 62 colonnes, mais donne seulement le nombre de colonnes mises à jour. Il est facile de lien avec "syscolumns" pour obtenir le nom
Sympa, mais pour info, quand il ya une lacune dans column_id dans sys.les colonnes (ex de la colonne supprimée), le code ci-dessus ne permet pas de détecter. Ex avec un tableau de 26 la colonne, le résultat est [1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27] alors qu'il n'y a pas de colonne avec column_id = 9
il ne fonctionne pas comme prévu. Parfois, il travaille pour 1 champs, parfois cela fonctionne, parfois, il a échoué complètement (sur la base de la requête, mais non randomisée de sortie pour la même requête). Je suis l'aide de SQL server 2014(120)!
Je tiens à préciser que
COLUMNS_UPDATED
n' PAS 62 colonne limitation - les données dans le champ varbinary(max), qui est de 2^31-1 octetsOriginalL'auteur podosta
J'ai une autre solution complètement différente qui n'utilise pas COLUMNS_UPDATED à tous, ni ne s'appuient sur la construction de SQL dynamique lors de l'exécution. (Vous pouvez utiliser du SQL dynamique au moment de la conception, mais c'est une autre histoire.)
Fondamentalement, vous commencez avec les tables inserted et deleted, unpivot chacun d'entre eux de sorte que vous êtes juste à gauche avec la clé unique, la valeur du champ et le nom de champ des colonnes pour chaque. Puis vous rejoignez le deux et le filtre pour tout ce qui a changé.
Voici une exemple de travail, y compris quelques appels de test pour montrer ce qui est enregistré.
Donc pas de déconner avec le bigint bitfields et arth des problèmes de dépassement. Si vous connaissez les colonnes que vous souhaitez comparer au moment de la conception, alors vous n'avez pas besoin de tout le SQL dynamique.
Sur le revers de la médaille, la sortie est dans un format différent et toutes les valeurs de champ sont convertis en sql_variant, la première pourrait être fixé par pivotement de la sortie de nouveau, et le second pourrait être fixé par la refonte de retour pour les types en fonction de vos connaissances de la conception de la table, mais ces deux aurait besoin d'un peu complexe sql dynamique. Ces deux pourrait ne pas être un problème dans votre XML de sortie. Cette question fait quelque chose de comparable à la sortie de retour dans le même format.
Edit: d'Examiner les commentaires ci-dessous, si vous avez un naturel clé primaire qui pourrait changer alors vous pouvez toujours utiliser cette méthode. Vous avez juste besoin d'ajouter une colonne qui est rempli par défaut avec un GUID à l'aide de la fonction NEWID (). Vous pouvez ensuite utiliser cette colonne à la place de la clé primaire.
Vous voudrez peut-être ajouter un index à ce domaine, mais comme supprimé et inséré tables dans un déclencheur sont en mémoire, il ne pourrait pas obtenir utilisé et peut avoir un effet négatif sur les performances.
Avez-vous un problème de performance? Rappelez-vous "...l'optimisation prématurée est la racine de tout mal." (Donald Knuth)
Je pense qu'il y a un problème. Votre déclencheur suppose que la clé primaire n'a pas changé, quand il peut. Donc, vous auriez besoin de séparer les insert/update/delete cas de toute façon qui signifie que vous pouvez simplement ignorer insérer/supprimer des cas tout à fait. Pour la mise à jour des cas, vous aurez besoin de les rejoindre, insérés ou supprimés par la ligne de l'index.
Vrai ce code suppose une substitution de clé primaire par opposition à naturel une situation qui pourrait changer. Mais si votre clé peut changer comment savez-vous qu'il a changé de ligne et pas une autre? Je pense que vous avez un problème différent de l'OP.
Le problème, je vais discuter est le même que celui de l'OP, c'est simplement pour connaître TOUS les changements RÉELS à l'intérieur d'un déclencheur after. Votre solution échoue lorsque la clé de substitution est changé et pour le BLOB, TEXT, XML champs (puisqu'ils ne peuvent pas être exprimés en sql_variant). Les champs de type Blob de côté, la bonne façon d'identifier la ligne n'est pas par sa clé de substitution, mais par son index à l'intérieur de la insérés ou supprimés des tables temporaires. Le insérés ou supprimés ont un 1-1 bijection pour JOUR APRÈS le déclenchement. C'est pourquoi, insérer et supprimer des déclencheurs after n'a pas d'importance ici.
OriginalL'auteur Stephen Turner
Je l'ai fait en tant que simple "one-liner". Sans aide, de pivot, de boucles, de nombreuses variables etc. qui fait de la recherche comme de la programmation procédurale. SQL doit être utilisé pour traiter des ensembles de données :-), la solution est:
Il utilise COLUMNS_UPDATED, prend soin de plus de huit colonnes - il gère autant de colonnes que vous le souhaitez.
Il prend soin sur le bon ordre des colonnes qui devrait être d'obtenir l'aide de COLUMNPROPERTY.
Il est basé sur la vision Les COLONNES de sorte qu'il peut inclure ou exclure uniquement les colonnes spécifiques.
Inserted
ouDeleted
tables.Insérés ou Supprimés sont pseudo résident en mémoire les tables ne sont pas disponibles pendant l'exécution de sql dynamique donc, je voudrais select * into #tmpInserted de insérées select * into #tmpDeleted effacées et utiliser le #tmpInserted,#tmpDeleted dans votre sql dynamique
Ce lien MS soutien indique que COLUMNS_UPDATED ne fonctionne pas pendant plus de 32 colonnes. Votre code ne fonctionne pas avec 2008 R2 sur au moins 62 colonnes.
OriginalL'auteur Michał Powaga
Le seul moyen qui se présente à moi que vous pourriez faire cela sans codage en dur des noms de colonne serait de déplacer le contenu de la table supprimée à une table temporaire, puis de construire une requête basée sur la définition de la table de comparer le contenu de votre temp de la table et de la table, et le retour délimité liste des colonnes selon qu'ils font ou ne correspondent pas. Certes, le ci-dessous est élaboré.
OriginalL'auteur cmsjr
Le code ci-dessous fonctionne pour plus de 64 colonnes et enregistre uniquement les colonnes mises à jour. Suivez les instructions sur les commentaires et tout doit être bien.
OriginalL'auteur Rick