2009-08-09 11 views
1

Je dois mettre à jour plusieurs lignes dans une table Parts lorsqu'un champ d'une autre table change et que je souhaite utiliser un trigger. La raison du déclencheur est de nombreuses applications existantes et de modifier les données et je n'ai pas accès à tous. Je sais que certaines bases de données prennent en charge un For Each Row dans l'instruction trigger, mais Microsoft ne le pense pas.SQL Server déclenche l'équivalent "For Each Row"

Spécifiquement j'ai deux tables Pièces et Catégories.

Parts a # Part, category_id, NOM_ARTICLE et original et beaucoup d'autres choses

Catégorie a category_id et CATEGORY_NAME.

Original est une concaténation de Category_Name et NOM_ARTICLE séparés par un ':'

Par exemple Bracelets: BB129090

Si quelqu'un change la Category_Name (pour excample de bracelets à bracelets), le champ d'origine doit être mis à jour dans chaque ligne de la table Parts. Bien que ce soit un événement peu fréquent, il arrive assez de causer des problèmes.

Pas d'applications Web et de bureau utilise une utilisation originale

Toute l'application comptable seulement originale

Ma tâche est de maintenir la comptabilité et l'autre application en synchronisation.

Je n'ai pas conçu la base de données et la société qui a écrit le programme de comptabilité ne le changera pas.

Répondre

1

Je suppose que dans votre cas, il n'y a pas besoin d'un déclencheur de niveau ligne.

Vous pouvez faire comme un déclencheur UPDATE sur la table Catégorie quelque chose comme

IF UPDATE(Category_Name) 
    UPDATE Parts 
    SET Original = inserted.Category_Name + ':' + Part_Name 
    FROM Parts 
    INNER JOIN inserted ON Parts.Category_ID = inserted.Category_ID 

.

Si vous avez vraiment besoin d'un traitement par ligne (par exemple, d'une procédure stockée), vous avez besoin d'une boucle CURSOR ou WHILE insérée.

+0

L'IF uPDATE (original) ne sera jamais k - la colonne "Original" ne sera jamais mise à jour, n'est-ce pas? C'est la colonne Category_Name ou la colonne Part_Name qui peut être mise à jour et qui déclenche une mise à jour de la colonne "Original" –

+0

Plus, vous avez également besoin d'un trigger sur la table Parts, dans le cas où la colonne "Part_name" change la table Catégorie n'est pas suffisante –

+0

fixe Category_Name. votre question se concentre sur Category_Name, donc j'ai esquissé la solution pour Category_Name. Bien sûr, vous avez également besoin de fonctionnalités similaires dans un déclencheur de mise à jour sur les pièces – devio

0

Si vous pouvez modifier les schémas de table, sur l'option que vous auriez qui ferait en sorte que la colonne Original est toujours à ce jour, peu importe, est de faire Original une colonne calculée - une colonne qui est calculée à partir du Category_Name plus le nom de la pièce si nécessaire.

Pour cela, vous devez créer une fonction stockée qui va faire ce calcul pour vous - quelque chose comme ceci:

CREATE FUNCTION dbo.CreateOriginal(@Category_ID INT, @Part_Name VARCHAR(50)) 
RETURNS VARCHAR(50) 
WITH SCHEMABINDING 
AS BEGIN 
    DECLARE @Category_Name VARCHAR(50) 

    SELECT @Category_Name = Category_Name FROM dbo.Category 
     WHERE Category_ID = @Category_ID 

    RETURN @Category_Name + ': ' + @Part_Name 
END 

et vous devez ajouter une colonne à votre table Parts qui montrera le résultat de cette fonction pour chaque ligne de la table:

ALTER TABLE Parts 
    ADD Original AS dbo.CreateOriginal(Category_ID, Part_Name) 

le principal inconvénient réside dans le fait que pour afficher la valeur de la colonne, la fonction doit être appelée chaque fois, pour chaque ligne. D'autre part, vos données sont toujours à jour et toujours garanti d'être correct, quoi qu'il arrive. Aucun déclencheur nécessaire non plus.

Voyez si cela fonctionne pour vous - en fonction de vos besoins et de la quantité de données que vous avez, il pourrait très bien fonctionner pour vous.

Marc

1

la colonne d'origine constitue une violation 1NF, ce qui est une très mauvaise idée. Vous pouvez soit

  1. Ignorer la colonne complètement et la concaténer dans chaque requête (probablement pas la meilleure solution, mais je soutiens que c'est probablement mieux que le déclencheur).
  2. Créer une vue sur la table et avoir la colonne d'origine dans la vue (probablement ce que je ferais), ou
  3. Rendre original une colonne calculée, ce qui est le meilleur moyen si vous souhaitez créer un index sur elle.
+0

dépend de votre définition de 1NF - le mien est "ne contient pas plusieurs valeurs dans un seul champ" et cela n'est pas validé, IMO –

+1

Mine est "ne contient pas plusieurs valeurs dans un seul champ "et" ne contient pas la même information dans plusieurs champs ". – erikkallen

2

Ou une autre option: pourquoi ne pas créer juste une vue sur ces deux tableaux, pour votre service comptable, qui contient cette colonne concaténés:

CREATE VIEW dbo.AccountingView 
AS 
    SELECT 
    p.PartNo, p.Part_Name, p.Category_ID, 
    c.Category_Name + ':' + p.PartName as 'Original' 
    FROM 
    Parts p 
    INNER JOIN 
    Category c ON p.Category_ID = c.Category_ID 

Maintenant votre peuple comptables peuvent utiliser ce point de vue pour leurs rapports, il est toujours frais, toujours à jour, et vous n'avez pas à vous soucier de la mise à jour et insérer les déclencheurs et toutes ces choses délicates .....

Marc

Questions connexes