Pergunta

Eu sou muito novo para SQL eu posso trabalhar com instruções básicas com bastante facilidade, mas eu ainda não descobri laços ainda.

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  
}
Foi útil?

Solução

Você deve evitar loops em procedimentos armazenados.

SQL é uma linguagem declarativa, em vez das linguagens imperativas você está mais acostumado. Quase tudo que você quer fazer com um loop deve ser feita enquanto a operação baseada em conjunto ou em código cliente. Há, é claro, exceções, mas não tantos como você pensa.

Veja este:
Por que é tão difícil de fazer uma loop no T-SQL


Você perguntou como fazê-lo usando métodos baseados em conjunto. Vou fazer o meu melhor, mas há um bug no início de seu código que faz com que seja difícil ter certeza que eu estou lendo isso direito. A condição na primeira instrução INSERT corresponde à condição do loop foreach. Assim, ou o loop só vai executar uma vez (um registro retornado lá), ou a sua inserção é a inserção de vários novos registros por iteração (sim, inserir declarações podem adicionar mais de um registro de cada vez). E se está adicionando vários registros, por que você só obter a identidade criada pela última inserção?

Dito isso, eu acho que entendo bem o suficiente para mostrar uma coisa. Parece que você está apenas fazendo uma cópia de uma estimativa. Você também não explicam em que o valor @NewEstimateID vem. Se há uma tabela pai então que assim seja, mas seria útil conhecer.

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

O código acima faz a suposição do ServiceID + EstimateID é único dentro da tabela de EstimateJobHeader. Se este não for o caso, eu preciso saber o que coluna ou colunas que identificam unicamente uma linha na tabela, para que eu possa juntar-se o registro antigo com o novo e ter a certeza a relação é 1: 1.

Finalmente, a verificação de erros foi omitida por questões de brevidade.

Outras dicas

Dê uma olhada na declaração quando:

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

No entanto, dependendo do que você está tentando fazer, provavelmente há uma maneira melhor, baseada em conjunto para fazer o que você está tentando fazer, e deve considerar que em primeiro lugar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top