【问题标题】:Classic ASP - Split and Contains in a simple SQL query经典 ASP - 在简单的 SQL 查询中拆分和包含
【发布时间】:2009-10-07 19:55:36
【问题描述】:

我有以下 sql 查询:

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

此查询告诉从 ONE 类别中获取所有产品。我想要这样的能力,以便产品可以来自某些类别,而不仅仅是一个类别。

所以,我将[Product].ProductCategoryId字段改为varchar(50),并写了一些用逗号分隔的类别id,例如:

1,5,7,4

现在,我怎样才能让它在 SQL 查询中工作?在 ASP 中有 Split 和 Contains (http://www.devx.com/vb2themax/Tip/18364) 函数,但我如何在 SQL 中做到这一点?

谢谢,对不起英语...

【问题讨论】:

    标签: sql sql-server asp-classic split


    【解决方案1】:

    必须注意:切勿将用户提供的数据连接到 SQL 查询中;您正在向 SQL 注入攻击敞开大门。

    我之前的回答(使用“IN”)是基于一个错误的想法,即您正在从用户那里收集多个 ID,并针对具有一个值的列进行搜索。但是您正在做相反的事情 - 该列有多个值,并且您试图匹配来自用户的一个值。

    这是一个不好的方法。不要使用逗号分隔的值;添加具有一对多关系的新表。然后查询看起来像

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

    如果你真的想要做逗号分隔的事情,你可以使用 LIKE 和 % 通配符进行搜索,但它会很脆弱(例如,你必须确保 ID 为“2”不t 匹配 "12")。

    【讨论】:

    • 又是什么 xkcd 故事? ;-)
    • 显然我们希望他使用参数化查询/存储过程,但是我不认为你可以传入一个参数,比如说 @var = "1,2,3,4" 然后做一个 IN 就可以了。
    • 啊,那个这里
    • 谢谢,但我收到此错误:将 varchar 值 '1,2' 转换为数据类型 int 时转换失败。我打印了 sql 查询,结果是:SELECT * FROM Product WHERE ProductCategoryID IN (2) BTW:我不在乎 SQL 注入攻击!这是一个本地项目。
    • 等等,我误解了你的所作所为——数据库中的字段是带有逗号的字段。我将添加一个新答案。
    【解决方案2】:

    不是没有,但WHERE ProductCategoryId = " & Request.QueryString("CategoryId") 是一种非常棒的查询方式。

    你刚刚对疯狂的SQL injection 攻击敞开心扉。

    【讨论】:

      【解决方案3】:
      【解决方案4】:

      回顾所有注入问题,这是用于 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)
      

      一旦设置了 Numbers 表,就创建这个函数:

      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,,,')
      

      输出:

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多