我有以下while循环,它永远不会停止。它永远打印8结束。谁能告诉我为什么?
DECLARE @catID int
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
ORDER BY
categoryid
WHILE @catID IS NOT NULL
BEGIN
PRINT @catID --do something
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID
ORDER BY
categoryid
END
答案 0 :(得分:4)
以下是您的代码的逻辑问题:
@catID
成为NULL
@catID
为NULL
,WHERE
子句为TRUE
,并返回记录@catID
为NULL
,则WHERE
条件永远不会成立:WHERE categoryid > @catID
这样做的原因是,使用不等式将cateogoryid
与NULL
值进行比较将始终返回NULL
(未知),而不是真或假。
如何解决此问题:
您可以尝试在WHERE
子句中添加一个额外的检查,以允许返回NULL
分解记录:
WHILE @catID IS NOT NULL
BEGIN
PRINT @catID
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID OR @catID IS NULL
ORDER BY
categoryid
END
答案 1 :(得分:2)
在重新选择之前,您需要重新初始化变量@catID
至NULL
- 因为如果没有任何内容可供选择,则不会返回任何行和之前的值将保留在@catID
中(因此,它永远不会设置为NULL并且永远不会满足IS NOT NULL
条件。)
试试这个:
WHILE @catID IS NOT NULL
BEGIN
PRINT @catID --do something
SET @catID = NULL -- re-initilatize to NULL
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID
ORDER BY
categoryid
END
答案 2 :(得分:2)
您的问题必须是,DI
语句在某些时候找不到任何价值,并且不会为您的BP
变量分配任何新内容,并且与SELECT
变量完全相同它在之前的循环中。结果 - 你永远不会退出你的while语句。
代码段解释:
@catID
结果:
DECLARE @catID INT = 5;
DECLARE @Test TABLE
(
CategoryID INT
);
/**
* Notice that I do not insert into table intentionally,
* so that following query doesn't assign anything
* to @catID variable
*/
SELECT TOP (1) @catID = CategoryID
FROM @Test;
SELECT @catID AS [@catID];
此查询返回5,而不是您期望的@catID
-----------
5
。
使用子查询分配值将分配实际值,如果找不到任何内容,则分配NULL
,这意味着当没有类别高于NULL
时,它将变为{{1你的查询将转义循环。
@catID
答案 3 :(得分:0)
至于为何 这将每次返回零行 你已经有了top,所以没有categoryid> @catID
@catID未赋值null 它根本没有分配
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID
ORDER BY
categoryid
修复
DECLARE @catID int
DECLARE @count int = 1
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
ORDER BY
categoryid
WHILE @count > 0
BEGIN
PRINT @catID --do something
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID
ORDER BY
categoryid
Select @count = select count(*) FROM [Production].[Categories]
WHERE categoryid > @catID
END
但是你的逻辑有更多问题。获得前1后你就拥有它。没有更多的前1名。
或
DECLARE @catID int
DECLARE @catIDnew int
SELECT TOP(1)
@catID = categoryid
FROM
[Production].[Categories]
ORDER BY
categoryid
WHILE @catID IS NOT NULL
BEGIN
PRINT @catID --do something
@catIDnew = null
SELECT TOP(1)
@catIDnew = categoryid
FROM
[Production].[Categories]
WHERE
categoryid > @catID
ORDER BY
categoryid
@catID =@catIDnew
END