Domanda

Sono molto nuovo in SQL, posso lavorare con le istruzioni di base abbastanza facilmente ma non ho ancora capito i cicli.

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  
}
È stato utile?

Soluzione

Dovresti evitare i loop nelle procedure memorizzate.

SQL è un linguaggio dichiarativo, piuttosto che le lingue imperative a cui sei più abituato. Quasi tutto ciò che si desidera fare con un ciclo deve essere eseguito come operazione basata su set o nel codice client. Ci sono, ovviamente, eccezioni, ma non quante ne pensi.

Vedi questo:
Perché è così difficile fare un loop in T-SQL


Hai chiesto come farlo utilizzando metodi basati su set. Farò del mio meglio, ma c'è un bug all'inizio del tuo codice che rende difficile essere sicuro di leggerlo bene. La condizione sulla prima istruzione INSERT corrisponde alla condizione sul ciclo FOREACH. Quindi o il ciclo verrà eseguito solo una volta (un record restituito lì) oppure l'inserto sta inserendo diversi nuovi record per iterazione (sì, le istruzioni insert possono aggiungere più di un record alla volta). E se sta aggiungendo diversi record, perché ottieni solo l'identità creata dall'ultimo inserto?

Detto questo, penso di averlo capito abbastanza bene da mostrarti qualcosa. Sembra che tu stia solo facendo una copia di un preventivo. Inoltre, non spieghi da dove proviene il valore @NewEstimateID. Se esiste una tabella padre, così sia, ma sarebbe utile conoscerla.

/* 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

Il codice sopra riportato presuppone che ServiceID + StimaID sia univoco nella tabella StimaJobHeader. In caso contrario, devo sapere quale colonna o colonne identificano in modo univoco le righe nella tabella, in modo da poter unire il vecchio record con il nuovo ed essere sicuro che la relazione sia 1: 1.

Infine, il controllo degli errori è stato omesso per brevità.

Altri suggerimenti

Dai un'occhiata all'istruzione WHILE:

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

Tuttavia, a seconda di ciò che si sta tentando di fare, esiste probabilmente un modo migliore e basato su set per fare ciò che si sta tentando di fare, che è necessario considerare prima.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top