我正在处理存储过程以找到格式不正确的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
答案 0 :(得分:0)
首先:完全同意所有注释 - SQL中的循环几乎总是可以避免的。让我们忽略这一点并暂时回答这个问题。
你的代码中也存在拼写错误 - 我认为大多数都是偶然的。最让我担心的是你有两个FROM @Addr2Chck
和FROM #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