在执行sql语句时发生“跳过”,而使用rowcount的语句
我正在处理存储过程以找到格式不正确的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
第一:所有的意见完全一致 - 在SQL循环几乎都是可以避免的。让我们暂时忽略这个问题并回答这个问题。
在你的代码中也有错别字 - 我假设大多数都是偶然的。我最担心的是你有FROM @Addr2Chck
和FROM #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
啊,对错字感到抱歉 - 正在改变代码,使其尽可能通用。非常感谢!避免行数均匀分布的假设完全是我需要的,不知道我需要它。如果没有别的,这整个练习已经说明了一些不使用循环的极好理由。我非常感谢帮助! – atomickiwi
为什么不使用连接而不是while循环。 sql不是循环。 – Hogan
@Hogan是正确的,如果你可以帮助它,你不应该在SQL中使用任何循环。但是如果你真的必须使用CURSOR,你应该真正使用它。 –
您的proc在运行时数据是否被其他人更改?您可以尝试打印@ROWCOUNT以查看是否跳过任何行。我希望它不会漏掉它的数量,但现在的数据是如何变化的。 –