我是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
}
答案 0 :(得分: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表中是唯一的。如果不是这种情况,我需要知道哪些列或列确实唯一地标识表中的行,以便我可以使用new加入旧记录并确保关系是1:1。
最后,为简洁起见,省略了错误检查。
答案 1 :(得分:5)
看看WHILE声明:
http://msdn.microsoft.com/en-us/library/aa260676(SQL.80).aspx
但是,根据您的尝试,可能会有一种更好的,基于设置的方式来完成您想要做的事情,并且应该首先考虑这一点。