2009-03-03 115 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

更新了我的回答:在這裏張貼,這樣你就可以在你的用戶頁面上打個招呼。 – 2009-03-03 20:11:08

回答

6

您應該避免在存儲過程中出現循環。

Sql是一種聲明性語言,而不是您最習慣的命令式語言。幾乎所有你想要做的循環都應該以基於集合的操作完成,或者在客戶端代碼中完成。當然有例外,但不是你想象的那麼多。

看到這個:
Why is it so difficult to do a loop in T-SQL


你問我如何使用基於集合的方法來做到這一點。我會盡我所能,但在代碼早期有一個錯誤,很難確定我正確地閱讀它。第一條INSERT語句的條件與FOREACH循環的條件匹配。因此,循環將只運行一次(在那裏返回一條記錄),或者插入每次迭代插入幾條新記錄(是的,插入語句一次可以添加多條記錄)。如果它添加了多個記錄,爲什麼只有最後一個插入創建的身份?

這就是說,我覺得我明白了,足以讓你看到一些東西。看起來你只是在製作估算的副本。您也不會解釋@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 

上面的代碼假設ServiceID + EstimateID在EstimateJobHeader表中是唯一的。如果不是這種情況,我需要知道哪些列或哪些列唯一標識了表中的行,以便我可以將舊記錄與新記錄一起加入,並確保關係爲1:1。

最後,爲簡潔起見省略了錯誤檢查。

+0

我發佈了我想要完成的內容。我將如何去做基於集合的操作呢? – 2009-03-03 18:27:49