我有一个数组或字符串:
private static string[] dataNames = new string[] {"value1", "value2".... };
我的SQL数据库中有一个varchar类型的表。我想检查该列中是否存在字符串数组中的哪些值。
我试过了:
public static void testProducts() {
string query = "select * from my table"
var dataTable = from row in dt.AsEnumerable()
where String.Equals(row.Field<string>("columnName"), dataNames[0], StringComparison.OrdinalIgnoreCase)
select new {
Name = row.Field<string> ("columnName")
};
foreach(var oneName in dataTable){
Console.WriteLine(oneName.Name);
}
}
该代码不是实际代码,我只是想向您展示重要部分
您看到的代码根据dataNames[index]
它工作正常,但我必须运行该代码56次,因为该数组有56个元素,每次我更改index
请问有更快的方法吗?
比较不区分大小写
答案 0 :(得分:2)
传递值列表非常困难。传递a table-valued parameter需要在服务器上创建T-SQL数据类型。您可以传递包含参数的XML文档,并使用SQL Server convoluted XML syntax对其进行解码。
以下是一个相对简单的替代方案,适用于多达一千个值。目标是构建in
查询:
select col1 from YourTable where col1 in ('val1', 'val2', ...)
在C#中,您应该使用参数:
select col1 from YourTable where col1 in (@par1, @par2, ...)
您可以传递的内容如下:
var com = yourConnection.CreateCommand();
com.CommandText = @"select col1 from YourTable where col1 in (";
for (var i=0; i< dataNames.Length; i++)
{
var parName = string.Format("par{0}", i+1);
com.Parameters.AddWithValue(parName, dataNames[i]);
com.CommandText += parName;
if (i+1 != dataNames.Length)
com.CommandText += ", ";
}
com.CommandText += ");";
var existingValues = new List<string>();
using (var reader = com.ExecuteReader())
{
while (read.Read())
existingValues.Add(read["col1"]);
}
考虑到这个解决方案的复杂性,我选择Max&#39;或蒂姆的回答。如果表格非常大并且您无法将其复制到内存中,您可以考虑这个答案。
答案 1 :(得分:2)
尝试使用contains应返回所需的所有值
var data = from row in dt.AsEnumerable()
where dataNames.Contains(row.Field<string>("columnName"))
select new
{
Name = row.Field<string>("columnName")
};
答案 2 :(得分:2)
首先,您不应该在内存中但在数据库中过滤记录。
但是,如果您已经拥有DataTable
并且需要找到其中某个字段位于string[]
中的行,则可以使用Linq-To-DataTable
。
例如Enumerable.Contains
:
var matchingRows = dt.AsEnumerable()
.Where(row => dataNames.Contains(row.Field<string>("columnName"), StringComparer.OrdinalIgnoreCase));
foreach(DataRow row in matchingRows)
Console.WriteLine(row.Field<string>("columnName"));
使用Enumerable.Join
:
var matchingRows = dt.AsEnumerable().Join(dataNames,
row => row.Field<string>("columnName"),
name => name,
(row, name) => row,
StringComparer.OrdinalIgnoreCase);
答案 3 :(得分:0)
对不起,我这里没有很多相关的代码,但很久以前我做了类似的事情,所以我会尝试解释一下。
基本上我有一个很长的项目ID列表,我需要返回到客户端,然后告诉服务器它在任何特定时间加载了哪些。原始查询将值作为逗号分隔的字符串集传递(它们实际上是GUID)。问题是,一旦条目数达到100,用户就会有明显的滞后,一旦达到1000个可能的条目,查询花了一分半钟,当我们达到10,000时,我们只能说你可以煮沸水壶,在你回来之前喝茶/咖啡。
答案是坚持将值直接检查到临时表中,其中表的一行表示要检查的值。临时表是针对执行搜索的用户键入的,因此这意味着其他用户搜索不会相互损坏,并且当用户注销时,我们就知道搜索表中的哪些值可以被删除。
取决于此数据的来源取决于您加载参考表的最佳方式。但是一旦它存在,那么你的新查询将类似于: -
SELECT Count(t.*), rt.dataName
FROM table t
RIGHT JOIN referenceTable rt ON tr.dataName = t.columnName
WHERE rt.userRef = @UserIdValue
GROUP BY tr.dataName
此处的RIGHT JOIN应为您的每个参考表值提供一个值,如果该值未出现在您的表中,则包括0。如果您不关心哪一个不出现,那么将其更改为INNER JOIN将消除零。
WHERE子句是为了确保您的搜索仅返回您当前正在查找的唯一项目 - 设计应该考虑有一天会发生并发访问(即使它现在还没有) ,所以写一些东西来保护它是可取的。