Vous devez éviter les boucles dans les procédures stockées. Sql est un langage déclaratif, plutôt que les langages impératifs auxquels vous êtes le plus habitué. Presque tout ce que vous voulez faire avec une boucle doit être fait comme une opération basée sur un ensemble ou fait dans le code client. Il y a, bien sûr, des exceptions, mais pas autant que vous le pensez.
Voir ceci:
Why is it so difficult to do a loop in T-SQL
Vous avez demandé comment le faire en utilisant des méthodes basées-set. Je ferai de mon mieux, mais il y a un bogue au début de votre code qui fait qu'il est difficile de s'assurer que je le lis bien. La condition de la première instruction INSERT correspond à la condition de la boucle FOREACH. Ainsi, soit la boucle ne sera exécutée qu'une seule fois (un enregistrement y est retourné), soit votre insert insère plusieurs nouveaux enregistrements par itération (oui, les instructions insert peuvent ajouter plus d'un enregistrement à la fois). Et si vous ajoutez plusieurs enregistrements, pourquoi obtenez-vous seulement l'identité créée par le dernier insert? Cela dit, je pense que je le comprends assez bien pour vous montrer quelque chose. On dirait que vous faites juste une copie d'une estimation. Vous n'expliquez pas non plus d'où provient la valeur @NewEstimateID. S'il y a une table parent, alors il en sera ainsi, mais il serait utile de le savoir.
/* Where'd @NewEstimateID come from? */
/* If there are several records in EstimateJobHeader with @OldEstimateID,
* this will insert one new record for each of them */
INSERT EstimateJobHeader (ServiceID,EstimateID)
SELECT ServiceID, @NewEstimateID
FROM EstimateJobHeader
WHERE EstimateID= @OldEstimateID
/* Copy EstimateDetail records from old estimate to new estimate */
INSERT EstimateDetail (JobHeaderID, OtherCols)
SELECT (new.JobHeaderID,ed.OtherCols)
FROM EstimateJobHeader new
INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID
AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID
INNER JOIN EstimateDetail ed ON ed.JobHeaderID= old.JobHeaderID
/* Copy EstimateJobDetail records from old estimate to new estimate */
INSERT EstimateJobDetail (JobHeaderID, OtherCols)
SELECT (new.JobHeaderID,ed.OtherCols)
FROM EstimateJobHeader new
INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID
AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID
INNER JOIN EstimateJobDetail ejd ON ejd.JobHeaderID= old.JobHeaderID
Le code fait l'hypothèse ci-dessus le ServiceID + EstimateID est unique dans la table EstimateJobHeader. Si ce n'est pas le cas, j'ai besoin de savoir quelle colonne ou quelles colonnes identifient de façon unique les lignes de la table, afin que je puisse joindre l'ancien enregistrement avec le nouveau et être certain que la relation est 1: 1.
Enfin, la vérification des erreurs a été omise par souci de brièveté.
Mis à jour ma réponse: poster ici afin que vous soyez ping sur votre page d'utilisateur. –