假设我们想将一个值数组作为参数传递给SP,在SP中它被用作IN子句中的值。
在表现方面哪一个更好:
1-将值作为逗号分隔的字符串
传递即
Select * FROM myTable WHERE Id IN (@myConcatenatedValues)
OR
2-将值作为表变量传递包含一个将该值保存为行的列
即
Select * FROM myTable WHERE Id IN (Select Id from @myVariableTable)
提前致谢
答案 0 :(得分:5)
我使用以下3个查询快速测试了这个:
DECLARE @UsersInString VARCHAR(255) = '1, 2, 3, 4, 5, 6, 7, 8, 9, 10'
/* Prone to SQL Injection, do not use like this! Sanitise your inputs */
EXEC (' SELECT * FROM [dbo].[User] WHERE UserID IN ( ' + @UsersInString + ' ) ')
GO
和
DECLARE @UsersInTable TABLE (
UserID INT
)
INSERT INTO @UsersInTable
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
SELECT *
FROM [dbo].[User] U
JOIN @UsersInTable UT ON UT.UserID = U.UserID
和:
DECLARE @UsersInTable TABLE (
UserID INT
)
INSERT INTO @UsersInTable
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
SELECT *
FROM [dbo].[User] U
WHERE U.UserID IN (
SELECT UserID
FROM @UsersInTable
)
返回的实际执行计划表明我的情况下顶级查询更快;该查询仅使用Clustered Index Seek
。
中间查询速度略慢,Clustered Index Seek
它也在表变量上使用了Table Scan
。
底部查询与Clustered Index Seek
和Table Scan
一样慢,它还对表变量执行了Sort
;人们会假设尝试针对排序的聚集索引优化IN ()
查询。
然而,它在很大程度上取决于被查询列的索引;以及构建字符串或表变量所需的时间。
一个相当重要的旁注:将值作为逗号分隔的字符串传递可能会有风险;你必须使用字符串连接动态构造IN ()
语句;这可能会让你对SQL注入开放。