'跳绳'在使用rowcount

时间:2015-10-06 21:47:59

标签: sql-server stored-procedures while-loop batch-processing rowcount

我正在处理存储过程以找到格式不正确的Addr2行并自动更正它们,或将它们移动到例外表中。我已经取得了成功,在某种程度上 - 这是一个很好的选择 - 跳过'记录的方式,并且必须在处理所有行之前运行两到三次。这显然不是我想要的。在减少之后,我遇到了核心问题:

----以前的代码建立临时表#Addr2Chck,它插入可疑的订单记录并分配行号------

set @NumberRecords = @@ROWCOUNT
set @rowcount=1

WHILE @rowcount<= @NumberRecords
BEGIN

SELECT @Cusid= Cusid,
@OrderNum= Ordernum,
@StndAddr2= Addr2,
from @Addr2Chck
where ROWID=@ROWCOUNT

update corp_orders
set addr2=@Stnd2
from (SELECT rowed, t.OrderNum from #Addr2Chck c left join corp_orders t   
on c.ordernum=t.ordernum) as j
where corp_orders.ordernum=@ordernum and corp_orders.cusid=@cusid and    j.rowid=@rowcount

SET @ROWCOUNT= @ROWCOUNT + 1
END

显然在这个循环中会发生if-else语句,但是如果我不能让简单版本起作用,那么我将会到处都有冲击。我确信我错过了一些明显的东西并且已经发展出了心智盲目。

以下是我用作参考资料的一些资料: http://www.java2s.com/Code/SQLServer/Transact-SQL/UsingROWCOUNT.htm Using row count from a temporary table in a while loop SQL Server 2008

以及Microsoft SQL AdventureWorks教科书。

我需要通过记录而不是批处理来做这个记录,我确信这也是问题的很大一部分。

感谢您的时间!

ETA:这个链接是在项目开始时给我的,因为应该避免使用游标:http://www.sqlbook.com/SQL/Avoiding-using-SQL-Cursors-20.aspx

1 个答案:

答案 0 :(得分:0)

首先:完全同意所有注释 - SQL中的循环几乎总是可以避免的。让我们忽略这一点并暂时回答这个问题。

你的代码中也存在拼写错误 - 我认为大多数都是偶然的。最让我担心的是你有两个FROM @Addr2ChckFROM #Addr2Chck。这两者都是临时表的可能化身。使用BOTH可能是您问题的根源。

我的回答是假设一个TABLE VAR,比如

DECLARE @Addr2Chck TABLE (RowID INT PRIMARY KEY , CusID INT, OrderNum INT, Addr2 VARCHAR(99))

是的,请注意RowID上的KEY。导致错误的一个可能原因是您之前在RowID上使用了DUPLICATES(在您省略的代码中)。

我的建议:使用@@ ROWCOUNT或独立增量变量。

尝试类似此变体的内容。仍然是一个邪恶的循环,但它避免了RowID完全分布在行数上的假设。

DECLARE @RowIDNow INT
DECLARE @CusID INT, @OrderNum INT, @StndAddr2 VARCHAR(MAX)
-- test data
insert into @Addr2Chck values (1, 2,3,'norwalk')
insert into @Addr2Chck values (3, 4,5,'westchester')

SET NOCOUNT ON 
WHILE EXISTS (SELECT * FROM @Addr2Chck )  
BEGIN

SET @RowIDNow = (SELECT MIN( RowID ) FROM @Addr2Chck )
print CONVERT(VARCHAR(33),GETDATE(), 121) + ' # ' + STR(@RowIDNow) -- purely for illustration

SELECT @Cusid= Cusid,
   @OrderNum= Ordernum,
   @StndAddr2= Addr2
from @Addr2Chck
where ROWID=@RowIDNow

-- note: changed #Addr2Chck to @Addr2Chck
update corp_orders
   set addr2=@Stnd2
from (SELECT rowed, t.OrderNum from @Addr2Chck c left join corp_orders t   
   on c.ordernum=t.ordernum) as j
where corp_orders.ordernum=@ordernum and corp_orders.cusid=@cusid and       j.rowid= @RowIDNow

DELETE FROM @Addr2Chck WHERE RowID = @RowIDNow;
END -- of the evil look