【轉】SQL SERVER 存儲過程中變量的作用域


今天遇到一個很有趣的事情,以前沒有注意過,所以記下來。

先來看例子。

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

 

CREATE PROCEDURE GetOrderBeforeDays

    @BeforDays INT

AS

BEGIN

    IF @BeforDays < 0

    BEGIN

        DECLARE @Today DATETIME
        SET @Today = GETDATE()
        DECLARE @Date DATETIME
        SET @Date = DATEADD(DAY,@BeforDays,@Today)                                                                                                                                            SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Date,110)

    END
    ELSE
    BEGIN
    SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Today,110)
    END

END

GO

這個存儲過程創建時不會有什么問題,但實際執行時是不正確的,當參數大於0時並不能獲取當天的數據。仔細看會發現@Today變量的定義在第一個IF語句中,但是在ELSE語句中竟然也可以使用,這與C#中的用法有所不同。

 

原來SQL SERVER中,聲明變量的地方開始到聲明變量的批處理或存儲過程的結尾,因此在ELSE語句中也可以訪問到IF語句中定義的變量。

 

但這會引起一些不必要的錯誤。如前邊的例子中,雖然在ELSE語句中可以訪問到定義的變量,但是並沒有被賦值,所以執行時是查不到當天的定單的。

 

所以建議盡可能的把所有的變量和初始化都放在存儲過程的最開始,一眼就可以看出定義了哪些變量,並賦了什么值。這樣一來可以防止在大量的IF ELSE 語句中不小心重復定義相同的變量而引起不必要的麻煩,也可以避免像前邊的例子中的錯誤

 

 1 SET ANSI_NULLS ON
 2 
 3 GO
 4 
 5 SET QUOTED_IDENTIFIER ON
 6 
 7 GO
 8 
 9  
10 
11 CREATE PROCEDURE GetOrderBeforeDays
12 
13     @BeforDays INT
14 
15 AS
16 
17 BEGIN
18 
19     DECLARE @Today DATETIME
20 
21     SET @Today = GETDATE()
22 
23     DECLARE @Date DATETIME
24 
25     SET @Date = DATEADD(DAY,@BeforDays,@Today)
26 
27     IF @BeforDays < 0
28     BEGIN
29     SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Date,110)
30     END
31     ELSE
32     BEGIN
33     SELECT * FROM Orders WHERE CONVERT(VARCHAR(10),OrderDate,110) = CONVERT(VARCHAR(10),@Today,110)
34     END
35 
36 END
37 
38 GO

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM