在SQL Server數據庫中書寫復雜的存儲過程時,一般的做法是拼接字符串,最后使用EXEC sp_executesql '拼接的字符串' 查詢出結果。
先看一段代碼:
1 -- =============================================
2 -- Author: XXX
3 -- Create date: 2014-09-19
4 -- Description: 獲取學生列表信息
5 -- =============================================
6 ALTER PROCEDURE [dbo].[Sp_GetStudentList]
7 @StudentId INT --主鍵id
8 AS
9 BEGIN
10
11 SET NOCOUNT ON; 12
13 DECLARE @SqlSelectResult NVARCHAR(MAX) = ''; 14 SET @SqlSelectResult = 'SELECT * FROM Student AS s '; 15
16 IF (ISNULL(@StudentId, 0) > 0) 17 BEGIN
18 SET @SqlSelectResult = @SqlSelectResult + ' WHERE s.ClassId > ' + @StudentId; 19 END
20
21 PRINT (@SqlSelectResult); 22
23 EXEC sp_executesql @SqlSelectResult; 24
25 SET NOCOUNT OFF; 26 END
然后調用該存儲過程:EXEC Sp_GetStudentList 1。結果如下:
運行失敗。
仔細分析原因發現:存儲過程參數@StudentId 類型為INT(整形)型;而自定義變量@SqlSelectResult是NVARCHAR(MAX)字符串類型。
在23行,EXEC sp_executesql @SqlSelectResult;執行拼接字符串時,報錯,編譯器嘗試將字符串類型轉換成int類型失敗。
意思是:SQL Server中在拼接字符串時,所有的變量必須全部是字符串類型,才能正確拼接,否則報錯。
解決方法1:將非字符串類型的變量轉換為字符串類型,
將18行代碼修改為:
SET @SqlSelectResult = @SqlSelectResult + ' WHERE s.ClassId > ' + convert(nvarchar(10),@StudentId);
解決方法2:在存儲過程開始定義的時候,將參數定義為字符串類型
ALTER PROCEDURE [dbo].[Sp_GetStudentList] @StudentId NVARCHAR(10) --主鍵id AS
……