【问题标题】:SQL Select where values in List<string>SQL 选择 List<string> 中的值
【发布时间】:2009-03-02 14:35:47
【问题描述】:

有没有一种方法可以针对具有指向 ArrayList 或 List 的 where 子句的数据源(可能是 sql、oracle 或 access)创建查询?

示例:

Select * from Table where RecordID in (RecordIDList)

我已经看到了一些使用 Linq 的方法,但如果可以避免,我宁愿不使用它。

【问题讨论】:

    标签: .net sql ado.net


    【解决方案1】:

    您可以使用String.Join。试试这样的:

    String query = "select * from table where RecordId in ({0});";
    String formatted = String.Format(query, String.Join(",", list.ToArray()));
    

    作为旁注,这不会保护您免受 SQL 注入 - 希望这个示例能够为您指明正确的方向。

    【讨论】:

    • string.Join 的签名实际上是 (string, string[]),因此调用看起来更正确,类似于 string.Join(",", list.ToArray())。
    • 我会比您的陈述“不会保护您免受 SQL 注入”更进一步,并说这些东西是所有 SQL 注入之母。不过,更好的方法是做更多的工作。
    • 当然,在一般情况下,通过字符串连接构建 SQL 查询是一个坏主意,但如果 R​​ecordIds 列表是整数的强类型列表,则这种方法的 SQL 注入风险为零。
    【解决方案2】:

    我只做了你试图用逗号分隔的列表做的事情

    Select * from Table where RecordID in (1,2,34,45,76,34,457,34)
    

    或者结果来自一个单独的选择

    Select * from Table where RecordID in (select recordId from otherTable where afieldtype=1)
    

    我很确定你无法实现你所追求的......

    【讨论】:

      【解决方案3】:

      Linq 到 Sql。 RecordList 应该是 List&lt;T&gt;,而不是 ArrayListIList&lt;T&gt;

      IEnumerable<TableRow> query =
        from t in db.Table
        where RecordList.Any(r => t.RecordId == r)
        select t;
      

      这将生成带有参数的sql:

      SELECT *
      FROM Table
      WHERE RecordId in (@p0, @p1, @p2, @p3, @p4)
      

      Linq 将根据需要生成尽可能多的参数。一些数据库实现在可以接受的参数数量方面受到限制。 SqlServer2005 的参数限制是 2000 多一点...所以不要使用超过 2000 个元素的列表。

      【讨论】:

        【解决方案4】:

        您可以遍历您的数组并为每个数组添加一个参数到您的 SQL 中。这可以帮助您绕过 SQL 注入,但请确保在构建 SQL 语句时使用 StringBuilder 而不是字符串连接。

        例如

        StringBuilder sql = new StrignBuilder("select * from Table where ");
        for  (int i = 0; i < RecordIDLis.Length; i++)
        {
            if (i > 0) sql.Append (" OR ");
            sql.Append(" RecordID = @param" + i.ToString() + " ");
            IDbDataParameter param = new Param();
            param.value etc.
        }
        

        【讨论】:

          【解决方案5】:

          您可以编写一个表值用户定义函数,该函数接受一个 ID 列表并创建一个表,然后再次连接该函数的结果。这个article by Erland Sommarskog 描述了如何做到这一点。

          或者,您可以使用 SQL Server 2008 中的新表参数(我认为)。

          或者,正如 Manu 所说,您可以使用 XML。

          但是,我建议不要在接受的答案中使用 IN String.Join 方法,因为它就像要求 SQL 注入一样。

          【讨论】:

            【解决方案6】:

            使用 Linq to SQL,我假设实体框架可以执行以下操作:

            dataContext.Table.Where(t => RecordIDList.Contains(t.RecordID));
            

            将与 List 和 ArrayList 一起使用,因为它们都实现了 IEnumerable。

            Linq 和 Lambda 要求您反转 Contains 方法,但它确实有效并生成 SQL“IN ()”子句。

            【讨论】:

              【解决方案7】:

              如果您使用动态 SQL,您可以将括号的内容作为文字逗号分隔列表发送。否则,您可以使用 XML 变量发送多个值。见http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm

              【讨论】:

                【解决方案8】:

                你可以用一个用逗号分隔的示例字符串列表来做到这一点:

                SELECT value
                FROM STRING_SPLIT('red,green,blue', ',')
                WHERE TRIM(value) <> ''
                

                【讨论】:

                  【解决方案9】:

                  请注意 Linq to SQL = dead,来源:http://blogs.msdn.com/adonet/archive/2008/10/29/update-on-linq-to-sql-and-linq-to-entities-roadmap.aspx

                  如果你想实现这样的架构,你目前应该使用实体框架。

                  此外,如果您对“in”子句使用另一个选择查询(如 GordonB 建议),最好使用“exists”而不是“in”,例如:

                  select * from tablename where exists (select id from othertablename where fieldtype=1)
                  

                  【讨论】:

                  • JoelHess 没有询问 LinqToSql...问题包括 Oracle,因此 LinqToSql 应该被排除在该要求之外。
                  猜你喜欢
                  • 2014-11-16
                  • 1970-01-01
                  • 2013-03-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多