Вставка строки формы "GUID1, GUID2, GUID3 ..." в оператор IN в TSQL - PullRequest
2 голосов
/ 18 сентября 2008

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

ALTER PROCEDURE [dbo].[GetCountingAnalysisResults] 
    @RespondentFilters varchar
AS
BEGIN

@RespondentFilters = '''8ec94bed-fed6-4627-8d45-21619331d82a, 114c61f2-8935-4755-b4e9-4a598a51cc7f'''

DECLARE @SQL nvarchar(600)

SET @SQL = 
   'SELECT *
    FROM Answer
    WHERE Answer.RespondentId IN ('+@RespondentFilters+'''))
    GROUP BY ChosenOptionId'

exec sp_executesql @SQL

END

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

Ответы [ 5 ]

3 голосов
/ 18 сентября 2008

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

В противном случае ваша хранимая процедура уязвима для внедрения SQL. Рассмотрим следующее значение для @RespondentFilters:

@RespondentFilters = '''''); SELECT * FROM User; /*'

Ваш запрос будет более безопасным для анализа (т. Е. Проверки) значений параметров и объединения:

SELECT *
FROM Answer
WHERE Answer.RespondentId IN (SELECT [Item] FROM dbo.ParseList(@RespondentFilters))
GROUP BY ChosenOptionId

или

SELECT *
FROM Answer
INNER JOIN dbo.ParseList(@RespondentFilters) Filter ON Filter.Item = Answer.RespondentId
GROUP BY ChosenOptionId

Это также немного более эффективно, поскольку вы не имеете дело с динамическим SQL (sp_executesql будет кэшировать планы запросов, но я не уверен, точно ли он идентифицирует ваш запрос как параметризованный запрос, поскольку у него есть переменный список элементов в предложении IN).

2 голосов
/ 18 сентября 2008

Вам нужны одинарные кавычки вокруг каждого GUID в списке

@RespondentFilters = '''8ec94bed-fed6-4627-8d45-21619331d82a'', ''114c61f2-8935-4755-b4e9-4a598a51cc7f'''
1 голос
/ 18 сентября 2008

Я думаю, вам тоже нужны кавычки внутри строки. Попробуйте:

@RespondentFilters = '''8ec94bed-fed6-4627-8d45-21619331d82a'',''114c61f2-8935-4755-b4e9-4a598a51cc7f'''

Вы могли бы также рассмотреть синтаксический анализ @RespondentFilters во временной таблице.

1 голос
/ 18 сентября 2008

Похоже, у вас нет закрывающих кавычек вокруг ваших @RespondentFilters

'8ec94bed-fed6-4627-8d45-21619331d82a, 114c61f2-8935-4755-b4e9-4a598a51cc7f'

Поскольку GUID сравнивает строки, это не сработает.

Лучше всего использовать код, чтобы разбить список на несколько значений.

Примерно так:


-- This would be the input parameter of the stored procedure, if you want to do it that way, or a UDF
declare @string varchar(500)
set @string = 'ABC,DEF,GHIJK,LMNOPQRS,T,UV,WXY,Z'


declare @pos int
declare @piece varchar(500)

-- Need to tack a delimiter onto the end of the input string if one doesn't exist
if right(rtrim(@string),1)  ','
 set @string = @string  + ','

set @pos =  patindex('%,%' , @string)
while @pos  0
begin
 set @piece = left(@string, @pos - 1)

 -- You have a piece of data, so insert it, print it, do whatever you want to with it.
 print cast(@piece as varchar(500))

 set @string = stuff(@string, 1, @pos, '')
 set @pos =  patindex('%,%' , @string)
end

Код, украденный у Рэймонд Льюаллен

0 голосов
/ 20 сентября 2008

Спасибо вам всем за ваши ответы. Все они очень помогли. Я решил эту проблему, написав функцию разбиения, и она отлично работает. Это немного накладно на то, что я мог бы сделать, но вы знаете, крайний срок скрывается за углом:)

...