Как выполнить хранимую процедуру для списка постоянных значений? - PullRequest
0 голосов
/ 28 октября 2019

Я могу легко выполнить хранимую процедуру для одного значения:

EXEC FooStored @ID = 269

Но как мне выполнить то же самое, что хранится для многих значений, которые есть в списке (у меня список, разделенный запятыми,около 1000 постоянных значений, пришедших из-за пределов SQL).

Я думал что-то вроде:

EXEC FooStored @ID IN (269,270,274,280,282,292,300,320,324)  -- doesn't work

Редактировать: поскольку у меня нет прав для изменения этой процедурыили делать новые хранимые процедуры для этой БД, я бы предпочел решить это на уровне запросов, а не просить кого-то внести необходимые изменения для меня.

Ответы [ 4 ]

2 голосов
/ 28 октября 2019

Ниже приведен пример использования табличного параметра.

Из вашего комментария к ответу с разделением строк я вижу, что вы не хотите изменять существующий интерфейс хранимой процедуры. Рассмотрите возможность создания новой хранимой процедуры для интерфейса списка или перегрузки существующего интерфейса необязательным параметром списка, чтобы избежать критических изменений.

CREATE TYPE dbo.IntegerList AS TABLE(
    IntegerValue int NOT NULL PRIMARY KEY
    )
GO

CREATE PROC dbo.FooStored
    @IntegerList dbo.IntegerList READONLY
AS
SELECT *
FROM dbo.YourTable
WHERE ID IN(
    SELECT IntegerValue
    FROM @IntegerList
);
GO

DECLARE @IntegerList dbo.IntegerList;
INSERT INTO @IntegerList VALUES(269),(270),(274),(280),(282),(292),(300),(320),(324);
EXEC dbo.FooStored @IntegerList = @IntegerList;
GO
1 голос
/ 28 октября 2019

Вы должны использовать типы таблиц. В вашей хранимой процедуре используйте определяемый пользователем тип таблицы в качестве типа вашего значения. это может быть что-то вроде этого:

CREATE PROCEDURE FooStored 
(
    @IDs ListOfID READONLY
)
AS
.
.
.

ListOfID - это определенный пользователем тип таблицы, как вы можете видеть ниже:

CREATE TYPE ListOfID AS TABLE
(
    [ID] int NULL
)

, чтобы использовать вашу хранимую процедуру FooStored, которую вы должны сначалаобъявите временную таблицу и вставьте свои данные в эту временную таблицу и передайте ее хранимой процедуре. это может быть что-то вроде этого:

 DECLARE @list ListOfID
    INSERT INTO @list VALUES(1)
    INSERT INTO @list VALUES(2)
    EXEC FooStored @list
0 голосов
/ 28 октября 2019

Как сказали @ikram и @DanGuzman, единственный способ сделать это, не редактируя существующую процедуру или не создавая новую, - просто выполнить сохраненные N раз. Запрос может быть построен довольно быстро, например, с помощью Vim.

Начиная с файла (в реальности гораздо больше цифр):

269,270,274,280,282,292,300,320,324

И с помощью команд:

qqf,s<Enter><Esc>q
1000@q
<C-V>ggIEXEC FooStored @ID = 

Результат:

EXEC FooStored @ID = 269
EXEC FooStored @ID = 270
EXEC FooStored @ID = 274
EXEC FooStored @ID = 280
EXEC FooStored @ID = 282
EXEC FooStored @ID = 292
EXEC FooStored @ID = 300
EXEC FooStored @ID = 320
EXEC FooStored @ID = 324
0 голосов
/ 28 октября 2019

Вам нужно взять параметр как строку, разделенную запятыми, в хранимую процедуру, а затем проверить внутри хранимой процедуры ", если '@ID' присутствует в списке."

Если вы используете SQL Server 2016 и выше , вы можете использовать SPLIT_STRING() function.

Если вы используете более низкую версию SQL Server , тогда вы можете использоватьэта функция для разделения строки:

CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX(',', @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(',', @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END

Чтобы разделить строку внутри хранимой процедуры:

IF (@ID IN (SELECT * FROM dbo.splitstring(@CommaSeparatedString))

NB! Будьте осторожны с пробелами при использовании выше *Функция 1022 *. Для значений типа '269, 270, 274' -> пробел после запятой:

IF (@ID IN (SELECT RTRIM(LTRIM([Name])) FROM dbo.splitstring(@CommaSeparatedString))
...