【问题标题】:Dynamically creating an SQL query with many ANDs and ORs动态创建包含许多 AND 和 OR 的 SQL 查询
【发布时间】:2020-04-06 17:32:55
【问题描述】:

我有一个 .NET Forms 应用程序,它是一个制造跟踪系统。我有一个 DataGridView 和几个带有可检查项目的 ListViews 来过滤数据表。过滤器包括零件编号、充电编号、当前位置等。有 9 个 ListView 和 2 个 TextBox(输入经过严格检查)。现在,我在选中的项目上使用 For 循环将它们添加到 SQL 查询的 Where 子句中。我担心我的查询可能会变得非常低效。 该查询包括 13 个连接,我正在查询的主表有大约 2,000 行,但我可以看到它在接下来的几年中达到 100,000。

string query = @"SELECT top 1000 [column names] FROM [table names and joins] ";  

List<string> filters = new List<string>();

//
// Part Number 
//
if (ListViewPartNumber.CheckedItems.Count != 0)
{
    string PartNumberFilterString = " ( ";
    for (int i = 0; i < ListViewPartNumber.CheckedItems.Count; i++)
    {
        int PN_ID = ListViewPartNumber.GetCheckedValue( i );
        PartNumberFilterString += "SubAssembliesTable.PN_ID  = " + PN_ID;
        if ( i < ListViewPartNumber.CheckedItems.Count - 1 ) 
            PartNumberFilterString += " OR ";
    }
    PartNumberFilterString += " ) ";
    filters.Add(PartNumberFilterString);
}

它为每个已检查项目的列表视图添加到过滤器列表中。然后它将它们组合成一个字符串用于数据库查询。

//
// Create filter string
//
for ( int i = 0 ; i < filters.Count ; i++ )
{
    if ( i == 0 ) query += "\r\n where ";
    query += filters[ i ];
    if ( i < filters.Count - 1 ) query += " AND ";
}

query += " \r\nORDER BY [ColumnName]  desc ";

它工作正常,我没有注意到任何性能问题,但我担心我这样做完全错误。查询可能会以几十个 AND 和 OR 结束。

【问题讨论】:

  • 为什么不创建一个包含 250k 记录的测试表并针对它运行查询呢?到时候你就知道是不是问题了。
  • 这听起来更像是一个数据库设计而不是一个 C# 问题。我添加了相应的标签。但实际上,我们需要一些关于表格外观的信息来提供任何实际建议。如果您的服务器支持它,您可以将一些更常见的组合变成一个视图。这将使查询保持可读性,并允许服务器进行合理的缓存而不会遇到过时的数据。但是如果你有 13 个 连接,那么听起来很不对劲。
  • @Christopher 我认为您使用视图消除所有连接是正确的。但是,这并不能解决 where 子句中所有 AND 和 OR 的问题。
  • @MikePennie 基本上你可以构建自己的查询并将它们转换为 SQL 字符串查询,它可能会花费时间但它很感兴趣。检查 Azure 存储表查询生成器 TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "RawMaterial"); Read more。否则,找第 3 方 SQL query builder 以节省时间

标签: c# sql .net database database-design


【解决方案1】:

看起来列表框包含多个参考表的行

  • 检查相应的外键列是否已编入索引(不包括具有 2-3 个唯一值的非选择性列,例如“sex”或“enabled”)
  • 使用类似SubAssembliesTable.PN_ID IN (id1, id2, .. idN) 的代码sn-ps 而不是SubAssembliesTable.PN_ID=id1 OR SubAssembliesTable.PN_ID=id2 ...
  • 使用相当查询参数来避免 SQL 注入攻击
  • 添加一些性能测试以确保在并发模式下所需的响应时间

您还可以查看“Programming with databases”一书,其中包含对上述主题的更详细解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    相关资源
    最近更新 更多