2009-10-07 19 views
0

我有以下SQL查詢:經典ASP - 斯普利特和包含一個簡單的SQL查詢

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

這個查詢告訴讓所有的產品從一類。我希望產品能夠來自某些類別,而不是僅來自一個類別。

所以,我改變了[產品] .ProductCategoryId字段爲varchar(50),和wrriten某些類別ID在逗號分隔,例如:

1,5,7,4

現在,我怎樣才能在SQL查詢中工作?在ASP中有Split和Contains(http://www.devx.com/vb2themax/Tip/18364)函數,但我如何在SQL中執行此操作?

感謝,併爲英語抱歉...

回答

3

強制性說明:切勿將用戶提供的數據連接到SQL查詢中;你正打開自己的SQL注入攻擊。

我以前的回答(使用「IN」)是基於一個錯誤的想法,即您從用戶收集多個ID,並使用一個值進行搜索。但是你正在做相反的事情 - 該列有多個值,並且你試圖匹配來自用戶的一個值。

這是一個不好的方法。不要使用逗號分隔的值;添加一個具有一對多關係的新表。那麼該查詢將看起來像

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

如果你真的想要做的逗號分隔的事情,你可以使用LIKE和通配符%做搜索,但它會是脆弱的(例如,你將不得不作出確定「2」的ID不符合「12」)。

+0

又是什麼那是XKCD的故事嗎? ;-) – 2009-10-07 20:04:21

+0

顯然我們希望他使用參數化查詢/ sprocs,但是我不認爲你可以傳入一個讓我們說@var =「1,2,3,4」的參數,然後對它做一個IN 。 – 2009-10-07 20:04:34

+0

啊,那here。 – 2009-10-07 20:06:06

2

不是沒有,但WHERE ProductCategoryId = " & Request.QueryString("CategoryId")是做您的查詢的GOD AWFUL方式。

你剛剛開啓自己的瘋狂SQL injection攻擊。

1

回顧所有注入問題,這是用於TSQL列表操作的best source。在不閱讀整篇文章的情況下,需要創建一個非常快速的無循環TSQL方法來分割字符串。

你會最終有一個TSQL分割功能,並可以使用它像:

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,這是你需要做的,實現它是什麼。

對於這種方法的工作,你需要做的這一個時間表設置:

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) 

一旦表中設置了數字,創建此功能:現在可以輕鬆地

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 

你可以拆分CSV字符串轉換成表格,並加入就可以了:

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

OUTPUT:

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

(6 row(s) affected) 

你可以在一個CSV字符串傳遞到一個程序和過程僅排在給定的ID,或者只是用它像查詢:

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