Хранимая процедура с переменным числом параметров
У меня есть хранимая процедура, где мне нужно передать параметры, Но проблема в том, что я не уверен, сколько параметров будет приходить, это может быть 1, в следующем запуске может быть 5.
cmd.Parameters.Add(new SqlParameter("@id", id)
Может ли кто-нибудь помочь, как я могу передать это переменное количество параметров в хранимой процедуре?
Благодаря
Ответы
Ответ 1
Вы можете передать его в виде списка, разделенного запятыми, затем использовать функцию split и присоединиться к результатам.
CREATE FUNCTION dbo.SplitInts
(
@List VARCHAR(MAX),
@Delimiter CHAR(1)
)
RETURNS TABLE
AS
RETURN
(
SELECT Item = CONVERT(INT, 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
);
Теперь ваша хранимая процедура:
CREATE PROCEDURE dbo.doStuff
@List VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT cols FROM dbo.table AS t
INNER JOIN dbo.SplitInts(@List, ',') AS list
ON t.ID = list.Item;
END
GO
Затем, чтобы назвать это:
EXEC dbo.doStuff @List = '1, 2, 3, ...';
Вы можете увидеть некоторые фон, другие варианты и сравнения производительности здесь:
Однако на SQL Server 2016 или выше вы должны посмотреть STRING_SPLIT()
и STRING_AGG()
:
Ответ 2
Хранимые процедуры поддерживают необязательные параметры. Как и С# 4, вы можете указать значение по умолчанию с помощью =
. Например:
create procedure dbo.doStuff(
@stuffId int = null,
@stuffSubId int = null,
...)
as
...
Для параметров, которые вы не хотите передавать, либо установите их на null
, либо не добавьте их в cmd.Parameters
вообще. Они будут иметь значение по умолчанию в хранимой процедуре
Ответ 3
SQLServer позволяет передать параметр TABLE
в хранимую процедуру. Таким образом, вы можете определить тип таблицы, CREATE TYPE LIST_OF_IDS AS TABLE (id int not null primary key)
, изменить свою процедуру, чтобы принять переменную этого типа (она должна быть только для чтения).
Ответ 4
Рассматривали ли вы с помощью словарь для этой цели?
Это позволит вам передавать любое количество параметров в виде пар ключ-значение.
Тогда вам нужно просто пройти через словарь и добавить эти параметры в cmd.
void DoStuff(Dictionary<string, object> parameters)
{
// some code
foreach(var param in parameters)
{
cmd.Parameters.Add(new SqlParameter(param.Key, param.Value);
}
// some code
}
В самой хранимой процедуре вам нужно будет указать значения по умолчанию для параметров.
CREATE PROCEDURE DoStuff(
@id INT = NULL,
@value INT = NULL,
-- the list of parameters with their default values goes here
)
AS
-- procedure body
Ответ 5
Вот фрагмент кода, который разбивает строку на основе ,
качестве разделителя. Вы можете даже параметризовать запятую. Он полезен для систем, у которых еще String_split
функции String_split
:
DECLARE @startindex INT
DECLARE @commaindex INT
DECLARE @paramAsString VARCHAR(MAX) -- this represents the input param
DECLARE @param VARCHAR (1024)
DECLARE @paramsTable TABLE(param VARCHAR(1024) NOT NULL) -- the splitted params come here
SET @startindex = 1
WHILE @startindex < LEN(@paramAsString)
BEGIN
SET @commaindex = CHARINDEX(',', @paramAsString, @startindex)
IF @commaindex = 0
BEGIN
SET @param = SUBSTRING(@paramAsString, @startindex, LEN(@paramAsString))
SET @startindex = LEN(@settlementEntities)
END
ELSE
BEGIN
SET @param = SUBSTRING(@paramAsString, @startindex, (@commaindex - @startindex))
SET @startindex = @commaindex + 1
END
IF @se IS NOT NULL AND 0 < LEN(RTRIM(LTRIM(@param)))
BEGIN
SET @param = RTRIM(LTRIM(@param))
INSERT INTO @paramsTable (param) VALUES (@param)
END
END
Ответ 6
если у вас есть Sql Server 2008 или более поздняя версия, вы можете использовать параметр таблицы...
https://blog.sqlauthority.com/2008/08/31/sql-server-table-valued-parameters-in-sql-server-2008/