Существует множество способов передать список и выполнить проверку типов внутри 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;', ',');
Результат:
Msg 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
И это можно вызвать из .NET с помощьюстроковый параметр со строгой типизацией @List
без каких-либо проблем с внедрением SQL - если вы передадите параметр в правильный вызов с использованием StoredProcedure
commandType и не будете пытаться создать строку EXEC ...
самостоятельно.
В SQL Server 2008 вы могли бы пойти еще дальше и использовать табличные параметры (TVP), которые позволяют заполнять набор данных параметром хранимой процедуры, скажем, из DataTable.