【发布时间】:2009-03-02 14:35:47
【问题描述】:
有没有一种方法可以针对具有指向 ArrayList 或 List 的 where 子句的数据源(可能是 sql、oracle 或 access)创建查询?
示例:
Select * from Table where RecordID in (RecordIDList)
我已经看到了一些使用 Linq 的方法,但如果可以避免,我宁愿不使用它。
【问题讨论】:
有没有一种方法可以针对具有指向 ArrayList 或 List 的 where 子句的数据源(可能是 sql、oracle 或 access)创建查询?
示例:
Select * from Table where RecordID in (RecordIDList)
我已经看到了一些使用 Linq 的方法,但如果可以避免,我宁愿不使用它。
【问题讨论】:
您可以使用String.Join。试试这样的:
String query = "select * from table where RecordId in ({0});";
String formatted = String.Format(query, String.Join(",", list.ToArray()));
作为旁注,这不会保护您免受 SQL 注入 - 希望这个示例能够为您指明正确的方向。
【讨论】:
我只做了你试图用逗号分隔的列表做的事情
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)
我很确定你无法实现你所追求的......
【讨论】:
Linq 到 Sql。 RecordList 应该是 List<T>,而不是 ArrayList 或 IList<T>
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 个元素的列表。
【讨论】:
您可以遍历您的数组并为每个数组添加一个参数到您的 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.
}
【讨论】:
您可以编写一个表值用户定义函数,该函数接受一个 ID 列表并创建一个表,然后再次连接该函数的结果。这个article by Erland Sommarskog 描述了如何做到这一点。
或者,您可以使用 SQL Server 2008 中的新表参数(我认为)。
或者,正如 Manu 所说,您可以使用 XML。
但是,我建议不要在接受的答案中使用 IN String.Join 方法,因为它就像要求 SQL 注入一样。
【讨论】:
使用 Linq to SQL,我假设实体框架可以执行以下操作:
dataContext.Table.Where(t => RecordIDList.Contains(t.RecordID));
将与 List 和 ArrayList 一起使用,因为它们都实现了 IEnumerable。
Linq 和 Lambda 要求您反转 Contains 方法,但它确实有效并生成 SQL“IN ()”子句。
【讨论】:
如果您使用动态 SQL,您可以将括号的内容作为文字逗号分隔列表发送。否则,您可以使用 XML 变量发送多个值。见http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
【讨论】:
你可以用一个用逗号分隔的示例字符串列表来做到这一点:
SELECT value
FROM STRING_SPLIT('red,green,blue', ',')
WHERE TRIM(value) <> ''
【讨论】:
请注意 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)
【讨论】: