有很多方法可以传入列表并在 SQL 中进行类型检查。如果您使用存储过程而不是这种即席 SQL,您可以简单地将列表作为字符串参数传入并在过程中对其进行解析。如果列表有任何非整数,它将简单地出错。
例如这个函数:
CREATE FUNCTION [dbo].[SplitInts]
(
@List VARCHAR(MAX),
@Delimiter CHAR(1)
)
RETURNS TABLE
AS
RETURN ( SELECT Item FROM ( SELECT Item = x.i.value('(./text())[1]', 'int') FROM
( SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.') ) AS a CROSS APPLY [XML].nodes('i') AS x(i)
) AS y WHERE Item IS NOT NULL
);
GO
可以这样调用:
SELECT Item FROM dbo.SplitInts('1234, 1235, 1236', ',');
结果:
Item
----
1234
1235
1236
如果你尝试使用任何字符串,它会爆炸:
SELECT Item FROM dbo.SplitInts('1234; DROP TABLE bobbytables;', ',');
结果:
消息 245,级别 16,状态 1,第 1 行
转换时转换失败
nvarchar 值 '1234; DROP TABLE bobbytables;'数据类型为 int。
因此,使用该拆分函数,您的存储过程可以这样编写:
CREATE PROCEDURE dbo.GetMyTable
@List VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT t.col1, t.col2 --, ...
FROM dbo.myTable AS t
INNER JOIN dbo.SplitInts(@List, ',') AS i
ON t.Id = i.Item;
END
GO
这可以使用强类型字符串参数 @List 从 .NET 调用,而无需担心 SQL 注入 - 只要您使用 StoredProcedure commandType 将参数传递给正确的调用并且不要尝试自己构建EXEC ... 字符串。
在 SQL Server 2008 中,您可以更进一步并使用表值参数 (TVP),它可以让您将数据集 填充到来自 DataTable 的存储过程参数中。