Pregunta

Soy muy nuevo en SQL, puedo trabajar con declaraciones básicas con bastante facilidad, pero todavía no he descubierto los bucles.

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

Solución

Debes evitar los bucles en los procedimientos almacenados.

Sql es un lenguaje declarativo, en lugar de los idiomas imperativos a los que está más acostumbrado. Casi todo lo que desea hacer con un bucle debe hacerse como una operación basada en el conjunto o en el código del cliente. Hay, por supuesto, excepciones, pero no tantas como crees.

Ver esto:
Por qué es tan difícil hacer una bucle en T-SQL


Usted preguntó cómo hacerlo usando métodos basados ??en conjuntos. Lo haré lo mejor que pueda, pero hay un error al principio de su código que hace que sea difícil estar seguro de que lo estoy leyendo correctamente. La condición en la primera instrucción INSERT coincide con la condición en el bucle FOREACH. Por lo tanto, el ciclo solo se ejecutará una vez (un registro devuelto allí), o su inserción inserta varios registros nuevos por iteración (sí, las declaraciones de inserción pueden agregar más de un registro a la vez). Y si está agregando varios registros, ¿por qué solo obtiene la identidad creada por la última inserción?

Dicho esto, creo que lo entiendo lo suficientemente bien como para mostrarte algo. Parece que solo estás haciendo una copia de un presupuesto. Tampoco explica de dónde proviene el valor de @NewEstimateID. Si hay una tabla para padres, que así sea, pero sería útil saberlo.

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

El código anterior hace la suposición de que la ID de servicio + la ID de estimación es única dentro de la tabla Estimador de trabajo. Si este no es el caso, necesito saber qué columna o columnas identifican de forma única las filas en la tabla, para poder unir el registro antiguo con el nuevo y estar seguro de que la relación es 1: 1.

Finalmente, se omitió la verificación de errores por brevedad.

Otros consejos

Eche un vistazo a la declaración WHILE:

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

Sin embargo, dependiendo de lo que esté tratando de hacer, es probable que haya una forma mejor y basada en la configuración de hacer lo que está tratando de hacer, y debe considerar eso primero.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top