c#应用程序中的Sql过滤器和/或语句

本文关键字:语句 过滤器 Sql 应用程序 | 更新日期: 2023-09-27 18:10:20

我有一个c#应用程序,我有这个问题:当我运行这个代码片段:

第一种方法

public void GetList(List<string> liste, List<int> outliste)
{
    foreach( string s in liste){
        outliste.Add(SqlFunction(s));
    }
}
public int SqlFunction(string str)
{
    string query = "select id from user where name="+str;
    ...................
    // return the id
}

执行时间为51秒

第二种方式

public void SqlSecondWayFunction(List<string> liste, List<int> outliste)
{
   string query ="select id from user where (";
   foreach(string str in liste){
       query += "name=" str + "or  ";
   }
   query += " 1=0 )";
   ...................
   // fill outliste by the result of the query
}

执行时间为1分19秒!!!!!!!!!(liste的计数约为11000)。

所以我需要知道为什么第一种方式更快?

c#应用程序中的Sql过滤器和/或语句

第一个更快,因为它做的事情更少。它只选择记录的一个子集。

第二个比较慢,因为你要连接大量的字符串(这是相当慢的),以及在数据库上为每条记录执行数千次不必要的比较,只是返回每条记录。

基本上,您要求数据库将name列与表中每个记录的11,000个字符串进行比较。例如,如果表包含100,000条记录,那么您将进行1,100,000,000字符串比较。然后返回所有记录因为其中一个条件是"1 = 1"也就是总是为真

几点:

  • 在WHERE子句中添加OR的长列表通常不是很有效,因为首先解析一个非常长的查询字符串需要时间,而且数据库引擎为OR的长列表完成的内部工作
  • 您添加的最后一部分("OR 1=1")使WHERE子句始终测试为真!这和没有WHERE子句是一样的
  • 以上任何一种都可能导致您的第一个示例中许多简单查询所花费的时间少于一个低效的大型查询
  • 你应该考虑下列之一的用例:1)被加载数据表的id列表的"从用户选择id",调用DataTable.AsEnumerable()方法,然后加入到你的其他列表使用LINQ查询,2)列表加载到一个数据库表,然后使用SQL加入列表的用户表,或3)列表加载到一个以逗号分隔的字符串,使用SQL的算子代替你的名字= x = y或z name =构造或名称。

如果要将列表传递给SQL Server 2008,则使用表值参数。在数据库中,首先需要创建一个新的TYPE:

CREATE TYPE dbo.ListOfInt AS TABLE(Value INT);

你可以使用它作为参数,比如:

var table = new DataTable();
table.Columns.Add("Value", typeof(int));
for (int i = 0; i < liste.Count; i++)
{
    var row = table.NewRow();
    row[0] = liste[i];
    table.Rows.Add(row);
}
string sql = "SELECT ID FROM [User] WHERE ID IN (SELECT Value FROM @Liste)";
using (var connection = new SqlConnection("Your connection String"))
using (var command = new SqlCommand(sql, connection))
{
    connection.Open();
    var tvp = new SqlParameter("@Liste", SqlDbType.Structured).TypeName = "ListOfInt";
    tvp.Value = table;
    command.Parameters.Add(tvp);
    using (var reader = command.ExecuteReader())
    while (reader.Read())
    {
        outliste.Add(reader.GetInt("ID"));
    }
}