'Skipping' 发生在 sql while 语句使用 rowcount
'Skipping' occurs during sql while statement using rowcount
我正在开发一个存储过程来定位格式不正确的 Addr2 行并自动更正它们,或者将它们移至异常 table。在某种程度上,我已经成功了——sproc 'skips' 就像记录一样,并且在处理所有行之前必须 运行 两次或三次。这显然不是我想要的。精简之后,我来到了核心问题:
----前面建立temp的代码table#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:这个link是在项目开始时给我的,作为应该避免游标的原因:http://www.sqlbook.com/SQL/Avoiding-using-SQL-Cursors-20.aspx
首先:完全同意所有评论 - SQL 中的循环几乎总是可以避免的。让我们忽略它并暂时回答问题。
您的代码中也有拼写错误 - 我想大多数都是偶然的。最让我担心的是你同时拥有 FROM @Addr2Chck
和 FROM #Addr2Chck
。这两个都是临时 table 的可能化身。同时使用这两种方法可能是您问题的根源。
我的回答假设一个 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
我正在开发一个存储过程来定位格式不正确的 Addr2 行并自动更正它们,或者将它们移至异常 table。在某种程度上,我已经成功了——sproc 'skips' 就像记录一样,并且在处理所有行之前必须 运行 两次或三次。这显然不是我想要的。精简之后,我来到了核心问题:
----前面建立temp的代码table#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:这个link是在项目开始时给我的,作为应该避免游标的原因:http://www.sqlbook.com/SQL/Avoiding-using-SQL-Cursors-20.aspx
首先:完全同意所有评论 - SQL 中的循环几乎总是可以避免的。让我们忽略它并暂时回答问题。
您的代码中也有拼写错误 - 我想大多数都是偶然的。最让我担心的是你同时拥有 FROM @Addr2Chck
和 FROM #Addr2Chck
。这两个都是临时 table 的可能化身。同时使用这两种方法可能是您问题的根源。
我的回答假设一个 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