2008-09-18 19 views
2

J'ai une procédure stockée dans ma base de données, qui ressemble à ceciInsertion d'une chaîne de la forme « GUID1, GUID2, GUID3 ... » dans une déclaration IN dans TSQL

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 ('[email protected]+''')) 
    GROUP BY ChosenOptionId' 

exec sp_executesql @SQL 

END 

Il compile et exécute , mais de toute façon cela ne me donne pas de bons résultats, tout comme la déclaration IN ne fonctionnait pas. S'il vous plaît, si quelqu'un connaît la solution à ce problème, aidez-moi.

+0

En aparté, vous pouvez toujours utiliser une impression @SQL pour voir ce que l'état SQL ressemble comme quand il est exécuté. Vous pourriez y trouver quelque chose. – Craig

Répondre

1

Il semble que vous n'avez pas des citations de clôture autour de vos @RespondentFilters

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

Depuis GUIDs faire une comparaison de chaînes, qui ne va pas au travail.

Votre meilleur pari est d'utiliser du code pour diviser la liste en plusieurs valeurs.

Quelque chose comme ceci:


-- 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 

code volé Raymond Lewallen

1

Je pense que vous avez besoin des citations dans la chaîne aussi. Essayez:

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

Vous pouvez également envisager d'analyser les @RespondentFilters dans une table temporaire.

2

Vous avez besoin des guillemets simples autour de chaque GUID dans la liste

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

Vous devriez vraiment regarder à diviser la liste des GUIDs dans une table et se joindre à l'encontre de cette table. Vous devriez être en mesure de trouver beaucoup d'exemples en ligne pour une fonction table qui sépare une chaîne d'entrée dans une table. Dans le cas contraire, votre procédure stockée est vulnérable à l'injection SQL. Pensez à la valeur suivante pour @RespondentFilters:

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

Votre requête serait plus parsing sécurisé (c.-à valider) les valeurs des paramètres et rejoindre:

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

ou

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

Il est un peu plus efficace aussi, puisque vous n'avez pas affaire à du SQL dynamique (sp_executesql mettra en cache les plans de requête, mais je ne suis pas sûr qu'il identifiera correctement votre requête en tant que paramétré requête car il a une liste variable d'éléments dans la clause IN).

0

Réservoir pour tous vos ansewers. Ils ont tous beaucoup aidé. J'ai traité le problème en écrivant une fonction de division, et cela fonctionne très bien. C'est un petit peu frais de ce que j'aurais pu faire, mais vous savez, la date limite se cache dans le coin :)