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