1

我正在处理存储过程以找到格式不正确的Addr2行,并自动更正它们,或将它们移动到异常表中。在某种程度上,我已经取得了成功 - 杂志“跳过”记录的方式,并且必须在处理所有行之前运行两到三次。这显然不是我想要的。削下来后,我来到了核心问题:在执行sql语句时发生“跳过”,而使用rowcount的语句

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

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

WHILE @rowcount<= @NumberRecords 
BEGIN 

SELECT @Cusid= Cusid, 
@OrderNum= Ordernum, 
@StndAddr2= Addr2, 
from @Addr2Chck 
where [email protected] 

update corp_orders 
set [email protected] 
from (SELECT rowed, t.OrderNum from #Addr2Chck c left join corp_orders t 
on c.ordernum=t.ordernum) as j 
where [email protected] and [email protected] and [email protected] 

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

以及微软SQL AdventureWorks的教科书。

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

谢谢你的时间!

埃塔:此链接在项目为理由的开始是给我为什么光标应该避免:http://www.sqlbook.com/SQL/Avoiding-using-SQL-Cursors-20.aspx

+0

为什么不使用连接而不是while循环。 sql不是循环。 – Hogan

+0

@Hogan是正确的,如果你可以帮助它,你不应该在SQL中使用任何循环。但是如果你真的必须使用CURSOR,你应该真正使用它。 –

+0

您的proc在运行时数据是否被其他人更改?您可以尝试打印@ROWCOUNT以查看是否跳过任何​​行。我希望它不会漏掉它的数量,但现在的数据是如何变化的。 –

回答

0

第一:所有的意见完全一致 - 在SQL循环几乎都是可以避免的。让我们暂时忽略这个问题并回答这个问题。

在你的代码中也有错别字 - 我假设大多数都是偶然的。我最担心的是你有FROM @Addr2ChckFROM #Addr2Chck。这两种都可能是临时表的化身。使用BOTH可能是你的问题的根源。

我的回答假设一个表VAR,像

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

是什么,请注意行ID的钥匙。错误的一个可能原因是您之前在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 [email protected] 

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

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

啊,对错字感到抱歉 - 正在改变代码,使其尽可能通用。非常感谢!避免行数均匀分布的假设完全是我需要的,不知道我需要它。如果没有别的,这整个练习已经说明了一些不使用循环的极好理由。我非常感谢帮助! – atomickiwi