如果使用動態SQL,你應該使用參數化查詢和sp_executesql的,像這樣
CREATE TABLE T (StartRow INT, StartEnd INT, CategoryID INT);
INSERT T VALUES (1, 10, 124), (1, 10, 125), (1, 10, 126);
DECLARE @StartRow INT = 1;
DECLARE @StartEnd INT = 10;
DECLARE @CategoryId NVARCHAR(50) ='124); DROP TABLE T; --';
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'SELECT *
FROM T
WHERE StartRow = @Start
AND StartEnd = @End
AND CategoryID IN (' + @CategoryId + ')'
EXECUTE SP_EXECUTESQL @SQL, N'@Start INT, @End INT', @StartRow, @StartEnd;
Dynamic SQL Example
可以使用SQL-Server的XML擴展做到這一點沒有動態SQL,雖然我我不確定你是否想要,你可能想要運行一些測試來檢查性能。
DECLARE @StartRow INT = 1;
DECLARE @StartEnd INT = 10;
DECLARE @CategoryId NVARCHAR(50) ='124,125';
DECLARE @X XML = CAST(N'<root><catid>' + REPLACE(@CategoryID, ',', '</catid><catid>') + '</catid></root>' AS XML);
SELECT StartRow,
StartEnd,
CategoryID
FROM T
INNER JOIN
( SELECT [CatID] = cat.value('.', 'int')
FROM @X.nodes('/root/catid') c (cat)
) c
ON c.CatID = CategoryID;
Example using XML Extension
查詢基本轉換你的逗號delimted字符串轉換成XML,然後拆分XML到它自己的表。
這應該也會降低sql注入的風險,因爲任何格式錯誤的字符串都會拋出錯誤而不是運行。考慮到這些變量:
DECLARE @StartRow INT = 1;
DECLARE @StartEnd INT = 10;
DECLARE @CategoryId NVARCHAR(50) ='124,125); DROP TABLE T; --';
與XML擴展方法運行會給這個
Msg 245, Level 16, State 1, Line 13
Conversion failed when converting the nvarchar value '124,125); DROP TABLE T; --' to data type int.
SQL Injection Fail with XML Extensions
與動態SQL運行後會取得理想的結果,但下一次你來運行它你會得到:
Msg 208, Level 16, State 1, Line 1
Invalid object name 'T'.
SQL Injection Example
有分割字符串,而不是上面使用的XML方法,其他的方法,但它僅僅是演示動態SQL不是唯一的出路,如果你沒有你的輸入字符串的控制,然後不使用它會更明智,因爲惡意字符串會破壞您的數據!
對於您還可以使用表值參數答案的完整性的緣故。例如
CREATE TYPE dbo.IntegerList AS TABLE (value INT);
CREATE PROCEDURE dbo.ExampleProcedure @StartRow INT, @StartEnd INT, @CategoryID dbo.IntegerList READONLY
AS
BEGIN
SELECT *
FROM T
WHERE StartRow = @StartRow
AND StartEnd = @StartEnd
AND CategoryID IN (SELECT Value FROM @CategoryID)
END
你不能這樣做,你必須使用動態SQL。沒有時間寫出如何現在,但你可以查看它。同時查看動態SQl的陷阱。 – HLGEM