Je maintient du code qui a une gâchette sur une table pour incrémenter une colonne. Cette colonne est ensuite utilisée par une application tierce a em>. Disons que la table s'appelle test em> avec deux colonnes num1 em> et num2 em>. La gâchette fonctionne sur chaque insertion de num1 em> dans test em>. Voici la gâchette: Cela fonctionne bien dans des inserts simples à base de lignes, mais il existe une autre application de 3ème partie b em> (soupir) qui fait parfois plusieurs insertions à ce sujet. Table de quelque chose comme ça, mais pas exactement: p> Ceci provoque une capacité de se comporter de manière erratique ... P> Maintenant, je n'ai pas accès à la source de l'application a em> ou b em> et contrôlez uniquement la base de données et la gâchette. Y a-t-il quelque chose qui peut être fait avec la gâchette de sorte que les mises à jour effectuées pour num2 em> sont correctes en cas de multiples inserts? P> solution: STRUT> p> Suivant est la solution basée sur le code de Affan: p> vérifier ici pour une approche définie:
SQL Server - Réécrivez la gâchette pour éviter une approche basée sur le curseur p> p>
4 Réponses :
Jetez un coup d'œil à Voir ici pour plus d'informations: P>
Comment tester plusieurs Actions de ligne dans une gâchette SQL Server? P> inséré code> pseudo table dans votre déclencheur car il contiendra plusieurs rangées au cours de ces opérations. Vous devez toujours gérer plusieurs rangées dans vos déclencheurs de toute façon. P>
La gâchette doit être réécrite pour gérer plusieurs inserts de rangée. Ne jamais écrire un déclencheur comme ça à l'aide de variables. Tous les déclencheurs doivent considérer qu'AlaWys considère que quelqu'un quelqu'un va faire une insertion / mise à jour / suppression de plusieurs lignes. P>
Vous ne devriez pas incrémenter des colonnes de cette manière dans une gâchette non plus, si vous avez besoin de numéros de colonne incrémentés, pourquoi n'utilisez-vous pas une colonne d'identité? p>
Je n'ai pas aimé la façon dont les colonnes étaient incrémentées non plus et j'ai même modifié la gâchette à Oracle pour utiliser une séquence. En ce qui concerne l'identité, ma première pensée était d'utiliser Alter Table pour la modifier à une identité, mais malheureusement, cela n'est pas possible et d'autres moyens de le faire nécessiter davantage de changements que je suis suffisamment courageux pour les dangers.
Il vous suffit d'ouvrir un curseur sur inséré et de l'itération pour @ proc_newnum1 et mettez votre reste de code que la boucle. e.g
Bien que ce qui précède ne soit pas tout à fait correct et que certaines erreurs, cela m'a aidé en me donnant une base pour travailler avec. J'ai ajouté la version mise à jour de ce qui précède dans ma question.
Je suis désolé, mais un curseur n'est pas le meilleur moyen de le faire.
@Cocowalla Vous faites un rejoindre code> entre la table insérée et la table de données de base. Pour obtenir des valeurs d'incrémentation pour la mise à jour, utilisez Row_Number () code> (SQL 2005 et UP) ou un insert sur une table TEMP avec une colonne d'identité ou une table de chiffres avec un million de lignes environ (ajoute uniquement 13 mégaoctets à la base de données). En fait, mieux que tout cela est de remplacer la colonne par une colonne d'identité qui donne déjà des valeurs incrémentées!
Comme déjà signalé, les curseurs peuvent être problématiques et il est préférable d'utiliser des jointures entre la table déclenchée et les tables insérées et supprimées.
Voici un exemple de comment faire: P>
ALTER TRIGGER [dbo].[TR_assign_uuid_to_some_varchar_column]
ON [dbo].[myTable]
AFTER INSERT, UPDATE
AS
BEGIN
/********************************************
APPROACH
* we only care about update and insert in this case
* for every row in the "inserted" table, assign a new uuid for blanks
*********************************************/
update t
set uuid_as_varchar = lower(newid())
from myTable t
-- inserted table is populated for row updates and new row inserts
inner join inserted i on i.myPrimaryKey = t.myPrimarykey
-- deleted table is populated for row updates and row deletes
left join deleted d on d.myPrimaryKey = i.myPrimaryKey
-- only update the triggered table for rows applicable to the trigger and
-- the condition of currently having a blank or null stored for the id
where
coalesce(i.uuid_as_varchar,'') = ''
-- you can also check the row being replaced as use that as part of the conditions, e.g.
or ( coalesce(i.uuid_as_varchar,'') <> coalesce(d.uuid_as_varchar,'') );
END
Un curseur B> à l'intérieur d'un déclencheur b> est une horriblement mauvaise idée b>; Les curseurs sont notoirement lents et des porcs de mémoire, et tout ce qui est dans un déclencheur devrait être aussi maigre et rapide que jamais humainement possible. Je voudrais fortement b> conseiller d'utiliser une approche différente (de ma propre expérience personnelle et angoissante avec de telles constructions)
Ne pouvait pas
si @ newnum2 est null code> vérifier être remplacé parcoalesce (max (num2), 0) code>?