2016-08-21 31 views
1

我有以下while循环,它永远不会停止。它永远打印出8。有人可以告诉我为什么吗?无限与T-SQL WHILE LOOP

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 

回答

2

您的问题一定是在某些时候你SELECT声明没有找到任何值,不指定任何新的东西到你的@catID变量,它保持,因为它是完全一样的先前的循环。因此 - 你永远不会退出你的while语句。

代码片段解释说:

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]; 

结果:

@catID 
----------- 
5 

该查询返回5,而不是NULL如你所愿。

分配使用子查询,如果没有的发现要么分配的实际值或NULL值,这意味着当没有类别高于@catID它将成为NULL和您的查询将难逃循环。

DECLARE @catID INT; 

SET @catID = (
    SELECT TOP (1) CategoryID 
    FROM Production.Categories 
    ORDER BY CategoryID 
    ); 

WHILE @catID IS NOT NULL 
BEGIN 
    PRINT @catID; 

    SET @catID = (
     SELECT TOP (1) CategoryID 
     FROM Production.Categories 
     WHERE CategoryID > @catID 
     ORDER BY CategoryID 
     ); 
END 
2

您需要重新初始化您的变量@catIDNULL再次选择之前 - 因为如果有什么可以选择,没有行会被退回,且前值将保持在@catID(因此,它从不被设置为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 
+0

Hy thanx为您的答案。但是它的错误,我认为是因为WHERE在SELECT之前执行,所以categoryis> NULL永远不会是真的。 – Breschi

4

这是合乎逻辑的问题与您的代码:

  • @catID成为NULL
  • 循环中断这就要求在查询中的第一个记录有@catIDNULL,
  • 这又将需要WHERE该记录的条款是TRUE,返回记录
  • 但是,如果@catIDNULL,那么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 
+0

Hy thanx为你的答案。你的代码仍然无处不在。我认为是因为WHERE在SELECT之前执行 – Breschi

+0

循环应该结束的逻辑是什么? –

0

至于为什么
这将每次都返回零行数
您已经拥有最佳排名,因此不会有categoryid> @catID

@CatID不分配它不是根本

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 

赋值为null
的值,但是你的逻辑有更多的问题。在获得前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 [email protected] 

END