2009-10-07 9 views
0

J'ai la requête SQL suivante:ASP classique - Split et contient dans une simple requête SQL

SQL = "SELECT * FROM Product WHERE ProductCategoryId = " & Request.QueryString("CategoryId")

Cette requête indique pour obtenir tous les produits d'une catégorie. Je veux la capacité pour que les produits puissent provenir de certaines catégories, et non d'une seule catégorie.

Alors, j'ai changé le champ [Produit] .ProductCategoryId à VARCHAR (50), et wrriten certaines catégories id séparés dans des virgules, par exemple:

1,5,7,4

Maintenant, comment puis-je obtenir ce travail dans la requête SQL? Dans ASP, il y a les fonctions Split et Contains (http://www.devx.com/vb2themax/Tip/18364), mais comment puis-je faire cela en SQL?

Merci, et désolé pour l'anglais ...

Répondre

3

Remarque obligatoire: Ne JAMAIS concaténer les données fournies par l'utilisateur dans une requête SQL; vous vous ouvrez aux attaques par injection SQL.

Ma réponse précédente (en utilisant "IN") était basée sur une idée erronée que vous étiez en train de collecter plusieurs ID de l'utilisateur, et de chercher sur une colonne avec une valeur. Mais vous faites le contraire - la colonne a plusieurs valeurs, et vous essayez de faire correspondre une valeur provenant de l'utilisateur.

C'est une mauvaise façon de le faire. N'utilisez pas de valeurs séparées par des virgules; ajouter une nouvelle table avec une relation un-à-plusieurs. Ensuite, la requête ressemblera

SQL = "SELECT Product.* FROM Product, ProductCategory WHERE ProductCategory.ProductId=Product.ID AND ProductCategory.CategoryId = " & Request.QueryString("CategoryId") 

Si vous voulez vraiment vraiment faire la chose séparés par des virgules, vous pouvez faire une recherche en utilisant des jokers aiment et%, mais il sera fragile (par exemple, vous devrez faire Assurez-vous qu'un identifiant de "2" ne correspond pas à "12").

+0

Ce qui est encore cette histoire xkcd? ;-) –

+0

De toute évidence, nous voudrions qu'il utilise des requêtes/sprocs paramétrés, mais je ne pense pas que vous puissiez transmettre un paramètre de @var = "1,2,3,4" et ensuite faire un IN dessus . –

+0

Ah, ça here. –

2

Pas pour rien, mais WHERE ProductCategoryId = " & Request.QueryString("CategoryId") est un Dieu de façon HORRIBLE faire votre requête.

Vous venez de vous ouvrir à des attaques folles SQL injection.

1

Si vous observez tous les problèmes d'injection, il s'agit de la manipulation best source pour la liste TSQL. Sans lire l'intégralité de l'article, voici ce qu'il faut pour créer une méthode TSQL très rapide et sans boucles pour séparer les chaînes.

Vous retrouvez avec une fonction split TSQL, et peut l'utiliser comme:

SELECT 
    y.* 
    FROM YourTable y 
     INNER JOIN dbo.FN_ListToTable(',','1,2,3,444,5,,,6') s ON y.ID=s.ListValue 

from the previous article, I prefer the number table approach et c'est ce que vous devez faire pour la mettre en œuvre.

Pour que cette méthode fonctionne, vous devez effectuer cette configuration de la table une seule fois: Une fois la table des numéros est mis en place

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

, créez cette fonction:

CREATE FUNCTION [dbo].[FN_ListToTable] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
( ---------------- 
    --SINGLE QUERY-- --this will not return empty rows 
    ---------------- 
    SELECT 
     ListValue 
     FROM (SELECT 
        LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue 
        FROM (
          SELECT @SplitOn + @List + @SplitOn AS List2 
         ) AS dt 
         INNER JOIN Numbers n ON n.Number < LEN(dt.List2) 
        WHERE SUBSTRING(List2, number, 1) = @SplitOn 
      ) dt2 
     WHERE ListValue IS NOT NULL AND ListValue!='' 
); 
GO 

Vous pouvez maintenant facilement diviser une chaîne CSV dans une table et se joindre à elle:

select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,') 

SORTIE:

ListValue 
----------------------- 
1 
2 
3 
4 
5 
6777 

(6 row(s) affected) 

Votre peut passer dans une chaîne CSV dans une procédure et ne traiter que des lignes pour les ID donnés, ou tout simplement l'utiliser dans la requête comme:

SELECT 
    y.* 
    FROM YourTable y 
     INNER JOIN dbo.FN_ListToTable(',',@GivenCSV) s ON y.ID=s.ListValue 
Questions connexes