--C語言中變數未賦值時是不確定值,T-SQL中變數未賦值時是NULLDECLARE @i int, @s varchar(100), @d datetimeSELECT @i, @s, @dGO--嚴謹起見,使用變數時最好賦初值,特別是依賴與變數初值的邏輯DECLARE @i int, @s varchar(100)SET @s = NULL --這句可省略,但假如未來版本中變數未賦值時不再是NULL,代碼會出錯。SET @i = 0WHILE @i < 5BEGIN SET @s = ISNULL(@s + ',', '') + CAST(@i AS varchar(10)) SET @i = @i + 1ENDSELECT @sGO--根據查詢為變數賦值CREATE TABLE #Nums( n int NOT NULL PRIMARY KEY CLUSTERED, n2 AS n * n, s AS CAST(n AS varchar(10)) + '^2 = ' + CAST(n * n AS varchar(10)))INSERT INTO #Nums(n)SELECT TOP(10) n = ROW_NUMBER() OVER(ORDER BY (SELECT 1))FROM sys.columnsGO--方法1:SET 變數 = 標量值(或標量子查詢)DECLARE @i1 int, @i2 intSET @i1 = (SELECT n FROM #Nums WHERE n = 1)SET @i2 = (SELECT MAX(n2) FROM #Nums)SELECT @i1, @i2GO--方法2:SELECT 變數 = 標量值(或列名)[ FROM ...]DECLARE @i1 int, @i2 intSELECT @i1 = n FROM #Nums WHERE n = 1SELECT @i2 = MAX(n2) FROM #NumsSELECT @i1, @i2GO--方法1與方法2的不同--a. 方法2可以一次為多個變數賦值DECLARE @i11 int, @i12 int, @i13 int, @i14 intDECLARE @i21 int, @i22 int, @i23 int, @i24 intSET @i11 = 3SET @i12 = 9SET @i13 = (SELECT n FROM #Nums WHERE n = 3) --查詢表兩次SET @i14 = (SELECT n2 FROM #Nums WHERE n = 3)SELECT @i11, @i12, @i13, @i14SELECT @i21 = 3, @i22 = 9SELECT @i23 = n, @i24 = n2 FROM #Nums WHERE n = 3 --查詢表一次SELECT @i21, @i22, @i23, @i24GO--b. 當查詢返回多行結果時,方法1是報錯,方法2是多次賦值(保持最後一個值)DECLARE @i1 intSET @i1 = (SELECT n FROM #Nums) --報錯GODECLARE @i2 intSELECT @i2 = n FROM #Nums --多次賦值並保持最後一個值SELECT @i2/*所謂“最後一個值”依賴於查詢返回結果集的順序。在不指定ORDER BY的情況下,查詢返回順序依賴於表中資料的實體儲存體順序和具體的執行計畫,順序是不確定的。*/GO--c. 當查詢返回空結果集(不是NULL)時,方法1是把空結果集轉換為NULL(標量)再賦值,方法2是不進行賦值操作DECLARE @i1 int, @i2 intSET @i1 = 11111 --初始值SET @i2 = 22222 --初始值SET @i1 = (SELECT n FROM #Nums WHERE 1 = 0)SELECT @i2 = n FROM #Nums WHERE 1 = 0SELECT @i1, @i2GO--因為目前SELECT賦值的本質是迴圈賦值,可以用以下方法拼接值:DECLARE @s varchar(100)SET @s = NULLSELECT @s = ISNULL(@s + ',', '') + CAST(n2 AS varchar(10))FROM #NumsORDER BY nSELECT @s--但微軟官方不保證這種SELECT賦值機制未來不會改變。GO--在SQL Server 2005之後可以用以下方法取代:DECLARE @s varchar(100)SET @s = STUFF((SELECT ',' + CAST(n2 AS varchar(10)) FROM #Nums ORDER BY n FOR XML PATH('')),1,1,'')SELECT @sGO--T-SQL變數範圍:在當前會話中,從變數聲明處到當前批的結束。--與代碼塊無關DECLARE @outer intSET @outer = 1BEGIN DECLARE @inner int SET @inner = 2 SELECT @outer, @innerENDSELECT @outer, @inner--只能通過參數傳遞到子會話EXEC sp_executesql N'SELECT @vo, @vi', N'@vo int, @vi int', @vo = @outer, @vi = @inner --調用預存程序和函數也是一樣PRINT '====到此為止是OK的===='--當前會話的變數範圍不能延伸到子會話EXEC('SELECT @outer, @inner') --調用預存程序和函數也是一樣GO--不能跨批SELECT @outer, @innerGO
http://topic.csdn.net/u/20101223/10/FFCC1E6F-92CE-4479-BF07-1DE46BF2A9BF.html