Question

Je suis très novice en SQL, je peux travailler avec les instructions de base assez facilement, mais je n’ai pas encore compris les boucles.

Foreach(JobHeaderID AS @OldJobHeaderID in dbo.EstimateJobHeader WHERE EstimateID=@OldEstimateID)  
{  
  INSERT EstimateJobHeader (ServiceID,EstimateID) 
  SELECT ServiceID, @NewEstimateID 
  FROM EstimateJobHeader 
  WHERE EstimateID=@OldEstimateID;  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 4 
    RETURN 4 
  END  

  SET @NewJobHeaderID = CAST(SCOPE_IDENTITY() AS INT)  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  

  INSERT EstimateDetail (JobHeaderID, OtherCols) 
  SELECT (@NewJobHeaderID,OtherCols) 
  FROM EstimateDetail 
  WHERE JobHeaderID=@OldJobHeaderID

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  

  INSERT EstimateJobDetail (JobHeaderID, OtherCols) 
  SELECT (@NewJobHeaderID, OtherCols) 
  FROM EstimateJobDetail 
  WHERE JobHeaderID=@OldJobHeaderID  

  SELECT @err = @@error 
  IF @err <> 0 
  BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
  END  
}
Était-ce utile?

La solution

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 effectué en tant qu'opération basée sur un ensemble ou en code client. Il existe bien sûr des exceptions, mais pas autant que vous le pensez.

Voir ceci:
Pourquoi est-il si difficile de faire une boucle dans T-SQL

Vous avez demandé comment procéder à l'aide de méthodes basées sur des ensembles. Je ferai de mon mieux, mais il y a un bogue dans votre code qui empêche de bien le lire. La condition de la première instruction INSERT correspond à la condition de la boucle FOREACH. Ainsi, la boucle ne sera exécutée qu'une seule fois (un enregistrement y est retourné) ou votre insertion insère plusieurs nouveaux enregistrements par itération (oui, les instructions d'insertion peuvent ajouter plusieurs enregistrements à la fois). Et s’il ajoute plusieurs enregistrements, pourquoi n’obtenez-vous que l’identité créée par la dernière insertion?

Cela dit, je pense que je le comprends assez bien pour vous montrer quelque chose. On dirait que vous ne faites que copier une estimation. De plus, vous n'expliquez pas d'où provient la valeur @NewEstimateID. S’il existe une table parente, qu’il en soit ainsi, mais il serait utile de connaître.

/* 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 ci-dessus suppose que 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 manière unique les lignes de la table, de manière à pouvoir joindre l'ancien enregistrement au nouvel enregistrement et être certain que la relation est 1: 1.

Enfin, la vérification des erreurs a été omise par souci de brièveté.

Autres conseils

Jetez un coup d’œil à l’instruction WHILE:

http://msdn.microsoft.com/en -us / library / aa260676 (SQL.80) .aspx

Cependant, selon ce que vous essayez de faire, il existe probablement une meilleure façon, basée sur les paramètres, de faire ce que vous essayez de faire, et vous devriez en tenir compte en premier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top