Fonction de mise à jour en TSQL déclencheur
J'ai une question à propos de TSQL fonction de mise à Jour. Par exemple, j'ai une table avec un champ Nom. Si je vérifie si le Nom du champ est modifié ou pas Après la mise à Jour de déclenchement aime ceci:
if Update(Name)
Begin
-- process
End
Sera la mise à Jour renvoie toujours VRAI même si le Nom n'est pas modifié? La mise à jour suivante déclaration de mise à jour avec la même valeur:
SELECT @v_Name = Name From MyTable Where Id = 1;
Update MyTable Set Name = @v_Name where Id = 1;
Si la mise à Jour() renvoie TRUE, même la valeur de Nom n'est pas modifié, ce que je dois comparer la valeur dans le inserted et deleted tables virtuelles pour savoir si la valeur est vraiment changé?
Par le chemin, la inserted et deleted sont des tables virtuelles et ils peuvent contenir plusieurs lignes de données si plusieurs lignes de données sont modifiées par un TSQL instruction INSERT ou UPDATE. Dans le cas de plus d'un records, le nombre de lignes dans inserted et deleted tables virtuelles de la même et quel est le véritable sens de la mise à Jour(Nom) comme VRAI? Ça veut dire que l'un au moins est-il changé? Ou effectue une mise à Jour(Nom) signifie que le champ de Nom a été fixé par instruction de mise à Jour, peu importe si la valeur est modifiée?
Le serveur SQL que j'utilise Microsoft SQL 2005.
Vous devez vous connecter pour publier un commentaire.
UPDATE()
peut être vrai, même si c'est la même valeur. Je ne voudrais pas compter sur elle personnellement et de comparer les valeurs.Deuxième,
DELETED
etINSERTED
ont le même nombre de lignes.La fonction Update() n'est pas par ligne, mais sur toutes les lignes. Une autre raison de ne pas l'utiliser.
Plus ici dans MSDN, mais c'est un peu clairsemée, vraiment.
Après le commentaire:
deleted
et**inserted**
tables virtuelles, droit? Je n'ai jamais entendu parler d'une "mise à jour" table virtuelledeleted
etinserted
seulement des tables ont le même nombre de lignes lors d'une mise à jour a été effectuée, ou lorsque les lignes sont affectées (dans un delete ou insert).Déclencheurs sont difficiles et vous avez besoin de penser en vrac quand vous êtes en train de créer un. Un déclencheur est activé une fois pour chaque instruction de mise à JOUR. Si l'instruction de mise à JOUR les mises à jour plusieurs lignes, le déclencheur ne sera qu'un feu qu'une seule fois. La fonction UPDATE() renvoie la valeur true pour une colonne lorsque cette colonne est inclus dans la mise à JOUR de la déclaration. Cette fonction permet d'améliorer l'efficacité de la déclenche en vous permettant de contourner la logique SQL lorsque cette colonne n'est même pas inclus dans la mise à jour de la déclaration. Elle ne vous dit pas si la valeur a changé pour une colonne dans une ligne donnée.
Voici un exemple de table...
Si l'instruction SQL suivante a été utilisée à l'encontre de ce tableau:
..et un APRÈS, d'INSERTION, de mise à JOUR déclencheur a été, en effet, cette instruction SQL serait toujours évaluer la fonction de mise à JOUR comme suit...
Noter que la mise à JOUR(SampleName) serait toujours vrai pour cette instruction SQL, indépendamment de ce que l'SampleName valeurs étaient avant. Elle renvoie true car l'instruction de mise à JOUR inclut la colonne SampleName dans la section JEU de cette clause, et ne repose pas sur ce que les valeurs sont avant ou après. La fonction UPDATE() ne sera pas de déterminer si les valeurs ont changé. Si vous souhaitez effectuer des actions en fonction de si les valeurs sont modifiées, vous allez avoir besoin d'utiliser SQL et de comparer les inserted et deleted lignes.
Ici est une approche pour garder une colonne dernière mise à jour de synchronisation:
La logique pour déterminer si la ligne a été mis à jour est dans la clause where ci-dessus. C'est le véritable vérifiez que vous devez faire. Ma logique est à l'aide de FUSIONNER pour gérer les valeurs NULL et INSERTS.
Noter que SI la mise à JOUR() vérification est utilisée pour aider à améliorer l'efficacité de la gâchette lorsque le SampleName colonne n'est PAS mis à jour. Si une instruction SQL de mise à jour de la Parent_SampleID colonne par exemple que SI la mise à JOUR(SampleName) vérifier permettrait pas de côté autour de la logique plus complexe dans la mesure où SI une déclaration n'a pas besoin de courir. Envisager l'utilisation de mise à JOUR() lorsque cela est approprié, mais pas pour les mauvaises raisons.
Aussi se rendre compte que, en fonction de votre architecture, la fonction de mise à JOUR peut avoir aucune utilité pour vous. Si votre code architecture utilise un intermédiaire qui met toujours à jour toutes les colonnes d'une ligne d'un tableau avec les valeurs de l'entreprise d'objet lorsque l'objet est enregistré, la fonction UPDATE() dans un déclencheur devient inutile. Dans ce cas, votre code est probablement toujours une mise à jour de toutes les colonnes avec chaque mise à JOUR de déclaration délivré à partir du niveau intermédiaire. Cela étant le cas, la mise à JOUR(columnname) fonction serait toujours vraies (true) lorsque les objets sont sauvés parce que tous les noms de colonnes sont toujours inclus dans la mise à jour des déclarations. Dans ce cas, il ne serait pas utile d'utiliser UPDATE() dans le déclenchement et le serait une charge supplémentaire en ce que le déclencheur pour une majorité de l'époque.
Voici quelques SQL de jouer avec le déclenchement ci-dessus:
Utilisateur GBN avait suggéré ce qui suit:
GBN la suggestion de l'utilisation d'un if (EXISTS( ...clause et de mettre de la logique dans le sens que SI une déclaration de lignes existent qui ont été modifiés pourraient travailler. Cette approche permettra d'incendie pour TOUTES les lignes comprises dans le déclencheur, même si seulement certaines lignes ont été réellement changé (ce qui peut être approprié pour votre solution, mais peut aussi ne pas être approprié si vous voulez seulement faire quelque chose pour les lignes où les valeurs modifiées.) Si vous avez besoin de faire quelque chose pour les lignes où un changement a eu lieu, vous avez besoin d'une logique différente dans votre SQL et qu'il a fournies.
Dans mes exemples ci-dessus, lorsque la mise à JOUR tblSample ENSEMBLE SampleName = 'Foo' émission de l'instruction et de la quatrième ligne est déjà 'foo', à l'aide de GBN l'approche de la mise à jour d'une "dernière modification datetime" colonne serait aussi de mise à jour de la quatrième ligne, qui ne serait pas appropriée dans ce cas.
Je suis d'accord que la meilleure façon de déterminer si une valeur de la colonne a en fait changé (plutôt que d'être mis à jour avec la même valeur) est de faire une comparaison des valeurs de la colonne dans le supprimé et inséré pseudo tables. Cependant, cela peut être une vraie douleur si vous voulez vérifier plus de quelques colonnes.
Voici une astuce je suis tombé sur un code, j'ai été le maintien d' (je ne connais pas l'auteur original):
L'utilisation d'un SYNDICAT et un GROUPE avec une clause HAVING pour déterminer les colonnes qui ont changé.
par exemple, dans le déclencheur, pour obtenir l'ID de l'lignes qui ont été modifiées:
C'est trop de travail lorsque vous êtes seulement à vérifier si une seule colonne a changé. Mais si vous êtes à la vérification de 10 ou 20 colonnes de l'UNION méthode est beaucoup moins de travail que
Je pense que le code suivant est mieux que les exemples ci-dessus, car il se concentre sur les colonnes que vous souhaitez vérifier de manière concise et efficace.
Il détermine si une valeur a changé seulement dans les colonnes spécifiées. Je n'ai pas étudié ses performances en comparaison avec les autres solutions, mais il est bien dans ma base de données.
Il utilise l'EXCEPTION de l'ensemble de l'opérateur à renvoyer toutes les lignes de la requête à gauche ne sont pas également trouvé sur la droite de la requête. Ce code peut être utilisé dans d'INSERTION et de mise à JOUR des déclencheurs.
La "PrimaryKeyID" colonne de la clé primaire de la table (peut être plusieurs colonnes) et est nécessaire afin de permettre la correspondance entre les deux séries.
Si vous souhaitez utiliser les lignes qui ont été modifiées dans la suite logique de déclencheur, j'ai l'habitude de mettre les résultats de l'EXCEPTION de la requête dans une variable de table qui peuvent être référencés plus tard.
J'espère que c'est de l'intérêt 🙂
La mise à jour de déclenchement de l'incendie sur tous mise à jour des déclarations. impactés par les lignes disponibles dans le déclenchement de la "insérée" et "supprimé" les tables. Vous pouvez comparer les anciennes et les nouvelles valeurs en comparant les PK colonnes dans les deux tables (si vous avez un PK). Le réelle tableau reste inchangé jusqu'à la déclencher la fin de l'exécution.