Может ли хранимая процедура иметь динамические параметры, которые будут использоваться в предложении «IN»? - PullRequest
6 голосов
/ 10 июня 2009

Я хочу выполнить запрос, подобный этому:

 SELECT * FROM Studio WHERE Id IN (134, 144, 132, 138, 7432, 7543, 2566)

но количество Id , переданных в предложение IN, определяется только во время выполнения.

Нужно ли использовать динамический SQL или это можно сделать с помощью хранимой процедуры?

UPDATE: Если какой-либо из вариантов доступен, какой из них лучше?

Спасибо.

Ответы [ 6 ]

8 голосов
/ 10 июня 2009

В зависимости от вашей версии Sql Server вы можете сделать это одним из двух способов.

Для Sql 2000/2005 вы можете использовать параметр (тип varchar), у которого есть список идентификаторов с разделителями. Создайте UDF, который будет анализировать varchar и возвращать таблицу, содержащую элементы. Затем добавьте предложение IN к таблице (т. Е. ... IN (выберите ID FROM @ReturnTable)).

Вот пример того, как будет выглядеть содержимое UDF: http://pietschsoft.com/post/2006/02/03/T-SQL-Parse-a-delimited-string.aspx

Для Sql 2008 вы можете сделать то же самое; однако вместо передачи параметра varchar вы можете просто перейти к поиску и передать параметр Table. Предложение IN по-прежнему имеет подзапрос, но все равно будет работать. Кроме того, если у вас есть таблица, вы можете просто выполнить внутреннее соединение и обойти необходимость в предложении IN.

РЕДАКТИРОВАТЬ: добавлен UDF для анализа ссылки строки с разделителями.

5 голосов
/ 10 июня 2009

Решение описано здесь:

Массивы и списки в SQL Server 2005

Текст SQL Эрланда Соммарскога, SQL Server MVP

http://www.sommarskog.se/arrays-in-sql-2005.html

3 голосов
/ 10 июня 2009

Вы можете сделать это в хранимой процедуре.

создайте временную таблицу внутри хранимой процедуры и вставьте значения, разделенные запятыми или любым разделителем, затем сделайте это

SELECT * FROM Studio WHERE Id IN (select id from temptable)

Затем удалите таблицу.

1 голос
/ 10 июня 2009

Вот UDF, который я использую с MSSQL 2000. Я где-то нашел это - извините, не могу вспомнить, где.

По сути, вы можете выполнить соединение в UDF, где первый параметр - это строка с разделителями, а второй параметр - это разделитель.

ВЫБРАТЬ t1.somecolumn из некоторого t1 ВНУТРЕННЕГО СОЕДИНЕНИЯ dbo.Split (@delimitedVar, ',') t2 ON t1.ID = t2.Element

CREATE FUNCTION [dbo].[Split]
(
@vcDelimitedString varchar(max),
@vcDelimiter varchar(100)
)
RETURNS @tblArray TABLE
   (
    ElementID smallint  IDENTITY(1,1), --Array index
    Element varchar(1000) --Array element contents
   )
AS
BEGIN
    DECLARE @siIndex smallint, @siStart smallint, @siDelSize smallint
    SET @siDelSize  = LEN(@vcDelimiter)
    --loop through source string and add elements to destination table array
    WHILE LEN(@vcDelimitedString) > 0
    BEGIN
        SET @siIndex = CHARINDEX(@vcDelimiter, @vcDelimitedString)
        IF @siIndex = 0
        BEGIN
            INSERT INTO @tblArray VALUES(@vcDelimitedString)
            BREAK
        END
        ELSE
        BEGIN
            INSERT INTO @tblArray VALUES(SUBSTRING(@vcDelimitedString, 1,@siIndex - 1))
            SET @siStart = @siIndex + @siDelSize
            SET @vcDelimitedString = SUBSTRING(@vcDelimitedString, @siStart , LEN(@vcDelimitedString) - @siStart + 1)
        END
    END
    RETURN
END
0 голосов
/ 10 июня 2009

объявите таблицу @temp и разбейте на нее значения. тогда вы могли бы сделать

выберите * из внутреннего соединения студии @temptable tb на s.ID = tb.ID

0 голосов
/ 10 июня 2009

В SQL 2008 вы можете использовать табличный параметр .

В SQL 2005 вы должны использовать динамический SQL, если только вы не хотите передать список как XML и использовать обработку XML в процедуре, чтобы измельчить XML обратно в переменную таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...