2009-03-03 5 views
2

저는 SQL에 매우 익숙합니다. 기본 구문을 상당히 쉽게 처리 할 수 ​​있지만 아직 루프를 찾지 못했습니다.저장 프로 시저의 sql2000 루프

Foreach(JobHeaderID AS @OldJobHeaderID in dbo.EstimateJobHeader WHERE [email protected]) 
{ 
    INSERT EstimateJobHeader (ServiceID,EstimateID) 
    SELECT ServiceID, @NewEstimateID 
    FROM EstimateJobHeader 
    WHERE [email protected]; 

    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 [email protected] 

    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 [email protected] 

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

내 대답이 업데이트되었습니다. 여기에 게시하면 사용자 페이지에서 핑이 발생합니다. –

답변

6

저장 프로 시저의 루프를 피해야합니다.

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

이를 참조하십시오
당신은 설정 기반의 방법을 사용하여 그것을 할 방법을 묻는 Why is it so difficult to do a loop in T-SQL


. 최선을 다할 것입니다.하지만 코드의 초기에 버그가있어서 제대로 읽는 것이 어렵습니다. 첫 번째 INSERT 문의 조건은 FOREACH 루프의 조건과 일치합니다. 따라서 루프는 한 번만 실행됩니다 (하나의 레코드가 거기에 반환 됨). 또는 삽입이 반복마다 여러 개의 새 레코드를 삽입합니다 (예 : 삽입 문은 한 번에 둘 이상의 레코드를 추가 할 수 있음). 그리고 여러 레코드를 추가하는 경우 마지막 삽입물에서 생성 된 ID 만 얻는 이유는 무엇입니까?

즉, 나는 당신에게 뭔가를 보여줄만큼 충분히 이해하고 있다고 생각합니다. 예상치를 복사하는 것 같습니다. 또한 @NewEstimateID 값의 출처를 설명하지 않습니다. 부모 테이블이 있다면 그렇게하는 것이 좋지만 알면 도움이 될 것입니다.

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

위의 코드는 서비스 id + EstimateID가 EstimateJobHeader 테이블 내에서 고유 한 가정을합니다. 그렇지 않은 경우 테이블의 행을 고유하게 식별하는 열이 무엇인지 알 필요가있어서 이전 레코드를 새로운 레코드와 조인 할 수 있고 관계가 1 : 1인지 확인할 수 있습니다.

마지막으로 간결성을 위해 오류 검사가 생략되었습니다.

+0

나는 내가 성취하려고하는 것을 올렸다. 세트 기반 작업에서 어떻게해야할까요? –