Affectant des lignes uniques et multiples
Vous devez être particulièrement conscients du fait que, dans certains produits de base de données, tels que SQL Server 2000, un déclenchement des incendies une fois pour chaque déclaration et non pas une fois pour chaque ligne concernée par une déclaration. Nous ne pouvons pas vous dire combien de fois nous avons vu les développeurs à rendre critique les erreurs de codage repose sur l'hypothèse très mal que leur code de déclenchement s'exécute une fois pour chaque ligne concernée par la déclaration plutôt qu'une seule fois pour toute l'instruction. Même Oracle, qui vous permet de définir des déclencheurs que le feu une fois pour chaque ligne concernée par une déclaration, peut toujours avoir des problèmes de modification de données correctement, comme vous le voyez plus tard. Vous avez plusieurs façons de contourner ce problème dans SQL Server 2000. Les parties suivantes jetez un œil à ces solutions de contournement. Si votre application est conçue de telle sorte que vous n'aurez jamais à insérer plus d'une seule ligne à la fois dans un tableau, vous pouvez simplement placer une restriction à cette table à cet effet en ajoutant le code de son déclencheur d'insertion. IF (@ @ ROWCOUNT! = 1) BEGIN RAISERROR 50010 'Vous ne pouvez pas entrer plus d'une ligne à la fois. "ROLLBACK TRANSACTION RETURN END CREATE TRIGGER ON tU_OrderItem OrderItem After Update AS BEGIN / * Declare variables pour une utilisation par le déclencheur * / DECLARE @ iOldQuantity INTEGER, @ iNewQuantity INTEGER, @ sOldItemNumber VARCHAR (15), @ sNewItemNumber VARCHAR (15) / * Get the old classés quantité et numéro de l'objet * / SELECT @ iOldQuantity = Quantité, @ = sOldItemNumber ItemNumber FROM Deleted / * Récupère le nouvel ordonné quantité et le numéro item * / SELECT @ iNewQuantity = Quantité, @ sNewItemNumber = ItemNumber DE Inséré / * Mise à jour du numéro de l'article vieux de mettre la quantité ancien ordre de revenir dans les stocks * / UPDATE InventoryItem SET AvailableToSell = AvailableToSell + @ iOldQuantity WHERE ItemNumber = @ sOldItemNumber / * Mise à jour le numéro d'article nouveau (il aurait pu changer) à Retirez la nouvelle quantité commandés auprès de l'inventaire * / UPDATE InventoryItem SET AvailableToSell = AvailableToSell - @ iOldQuantity WHERE ItemNumber = @ sNewItemNumber FIN Ce code de déclenchement exécute une seule fois et n'utilise que les valeurs de la première ligne de la Supprimé pseudotable, à son tour causer une seule ligne dans le tableau InventoryItem d'être mis à jour. Prenons le code nid. CREATE TRIGGER ON tU_OrderItem OrderItem Après MAJ AS BEGIN / * Placer l'ancienne quantité ordre de revenir dans les stocks * / UPDATE InventoryItem SET AvailableToSell = AvailableToSell + d.Quantity FROM Deleted d INNER JOIN ii InventoryItem ON d.ItemNumber = ii.ItemNumber / * Suppression de la nouvelle quantité commandés auprès de l'inventaire N'oubliez pas: le numéro de l'objet mai ont changé! * / UPDATE InventoryItem SET AvailableToSell = AvailableToSell - i.quantity DE Inséré i INNER JOIN InventoryItem ii sur i.ItemNumber = ii.ItemNumber FIN Ce code met à jour toutes les lignes de déclenchement InventoryItem qui correspondent aux lignes OrderItem mis à jour, même si la clé de la valeur change ItemNumber. En rejoignant la pseudo-insérés et supprimés avec la table InventoryItem, vous pouvez effectuer les calculs nécessaires pour augmenter et diminuer chaque article en stock par les quantités anciens et neufs commandés, respectivement. Le code est également beaucoup moins encombrants s'ils sont écrits correctement. Dans la pratique, vous auriez sans doute faire trois choses différemment. Premièrement, vous avez trois déclencheurs distincts pour accomplir cette tâche et un chacun pour les instructions INSERT, UPDATE, DELETE et les événements et chacun d'entre eux contiennent la logique spécifique pour ajuster le niveau des stocks en fonction de base de données de l'événement qui est survenu. Deuxièmement, vous placerez dans votre logique de déclenchement mise à jour pour changer la ItemNumber de sa valeur initiale. Troisièmement, vous permettrait de regrouper les deux requêtes UPDATE dans la détente dans l'une requête de rejoindre la table InventoryItem et les deux pseudo-tables, comme dans le code. CREATE TRIGGER ON tU_OrderItem OrderItem After Update AS BEGIN IF (UPDATE (ItemNumber)) BEGIN RAISERROR 50010 'Vous ne pouvez pas changer le numéro d'ordre. "ROLLBACK TRANSACTION RETURN END UPDATE InventoryItem SET AvailableToSell = ii.AvailableToSell + d.Quantity - i.quantity DE Inséré i INNER JOIN InventoryItem ii sur i.ItemNumber = ii.ItemNumber INNER JOIN Supprimé d ON d.ItemNumber = ii.ItemNumber FIN Imaginez la récupération d'un tas de lignes dans une place à part dans la mémoire et ensuite aller chercher ceux qu'on lignes à la fois, en regardant les valeurs de colonnes dans chaque ligne et effectuer éventuellement une opération fondée sur les valeurs de chaque ligne. Il s'agit de la vie d'un curseur. Curseurs sont un dernier recours parce qu'elles sont lourdes, lentes, et beaucoup de ressources, et elles détruisent l'évolutivité de votre base de données s'il est utilisé sur les zones à haut débit des transactions de votre base. Les curseurs sont souvent utilisées là où elles ne devraient pas être, en tant que substituts de bon code SQL ou pour contourner les bases de données sont mal conçues. Parfois, cependant, un curseur est la seule solution pratique à votre problème. Disons, par exemple, que vous avez une procédure stockée nommée sp_ArchiveCall qui est utilisé dans de nombreux endroits tout au long de votre base de données, y compris le déclencheur d'insertion indiqué dans le code. CREATE PROCEDURE sp_ArchiveCall (@ SupportCallID Integer) AS BEGIN UPDATE SupportCall SET Status = 60 Lorsque SupportCallID = @ SupportCallID END GO tI_SupportCallArchive CREATE TRIGGER ON SupportCallArchive AFTER INSERT AS BEGIN DECLARE @ SupportCallID Integer curClosedCalls DECLARE CURSOR FOR SELECT SupportCallID DE Inséré OPEN curClosedCalls FETCH NEXT FROM curClosedCalls EN TOUT SupportCallID @ @ @ FETCH_STATUS = 0 sp_ArchiveCall BEGIN EXECUTE @ SupportCallID FETCH NEXT FROM curClosedCalls dans @ SupportCallID END CLOSE curClosedCalls curClosedCalls DEALLOCATE END GO Vous utilisez un curseur ici parce que vous devez appeler la procédure stockée une fois pour chaque ligne affectée par la déclaration, et la seule façon de le faire est de placer l'appel de procédure stockée au sein de chaque extraction, ou de chercher d'une ligne du curseur. S'il vous plaît traiter tous les curseurs avec la peur et de dégoût. Ils sont mauvais, et vous feriez mieux d'avoir une excuse défendable pour les utiliser ou de votre source d'examen par les pairs de code est susceptible de vous gêner terriblement. un article présenté par Samuel Wardy Disclaimer:Notre site n'est pas responsable du contenu de cet article. Webarticles est une ressource d'information gratuite. Important: Cet article «affectant des lignes uniques et multiples» a été traduit par un logiciel automatique. Nous nous sentons désolés pour les fautes d'orthographe que mai ont eu lieu. Nous vous remercions de votre compréhension.
|
|||||
| Online: 229 users browsing the articles directory |
|
|