2016-08-21 80 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