문제

나는 SQL을 처음 접했지만 기본 진술로 상당히 쉽게 작업 할 수 있지만 아직 루프를 찾지 못했습니다.

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  
}
도움이 되었습니까?

해결책

저장된 절차에서 루프를 피해야합니다.

SQL은 가장 익숙한 명령 언어보다는 선언적 언어입니다. 루프로 원하는 거의 모든 것이 설정 기반 작업으로 수행하거나 클라이언트 코드에서 수행해야합니다. 물론 예외는 있지만 생각만큼 많지는 않습니다.

이것 좀 봐:
T-SQL에서 루프를하기가 어려운 이유


세트 기반 방법을 사용하여 수행하는 방법을 물었습니다. 최선을 다하겠습니다. 그러나 코드 초기에 버그가있어 제대로 읽고 있는지 확인하기가 어렵습니다. 첫 번째 삽입 문의 조건은 Foreach 루프의 조건과 일치합니다. 따라서 루프가 한 번만 실행되거나 (한 레코드가 반환 됨), 삽입물이 반복 당 여러 레코드를 삽입합니다 (예, 삽입 문은 한 번에 하나 이상의 레코드를 추가 할 수 있습니다). 그리고 여러 레코드를 추가하는 경우 왜 마지막 인서트에서 생성 된 신원 만 얻습니까?

즉, 나는 당신에게 무언가를 보여줄만큼 충분히 이해한다고 생각합니다. 당신은 단지 견적 사본을 만드는 것 같습니다. 또한 @newestimeid 값의 출처를 설명하지 않습니다. 부모 테이블이 있다면 그렇게되지만 알아 두는 것이 도움이 될 것입니다.

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

위의 코드는 ServiceID+extimeIdID가 thatimejobheader 테이블 내에서 고유하다는 가정을 만듭니다. 그렇지 않은 경우, 기둥이나 열이 테이블에서 어떻게 행을 고유하게 식별하는지 알아야하므로 새로 기존 레코드에 참여하고 관계가 1 : 1임을 확인할 수 있습니다.

마지막으로 간결하게 오류 검사가 생략되었습니다.

다른 팁

While 진술을 살펴보십시오.

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

그러나, 당신이하려는 일에 따라, 아마도 당신이하려는 일을하는 더 나은 세트 기반 방법이있을 것입니다. 그리고 먼저 그것을 고려해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top