簡體   English   中英

僅當過濾器值不是空字符串、空白或空值時才過濾 MySQL 查詢最佳實踐

[英]Filtering MySQL query only when the filter values are not empty-string, white-space or null best practice

我想在這里過濾列 A 的值,然后過濾列 B 等,但是我希望如果過濾器 valueA 只是一個空字符串,則不會發生過濾並且所有值都被接受。 如果 valueB 為空,則相同,則不會發生過濾。

這是一個通用的 mysql 查詢,我希望只在 valueA 或 valueB(包括或)具有非空、空格或空字符串的值時才進行過濾。

   using (var cmd = new MySqlCommand(
                    " SELECT columnA, columnB etc
                    " FROM table" +
                    " WHERE columnA = '" + valueA + "' " +
                    " THEN BY columnB = '" + valueB + "' " +
                    " GROUP BY columnA" +
                    " LIMIT 0, 100",
                    connection))
  • SQL 作為一種語言,不支持動態謂詞。
    • ISO SQL 設計委員會知道這一點,他們很高興看到我們都不得不使用他們非常不符合人體工程學和過於冗長的查詢語言。
  • 要使用條件謂詞或動態謂詞,您需要使用某種形式的字符串連接來重建查詢。
    • 有些人建議將查詢參數@value IS NULL OR [Column] = @value NULL並濫用@value IS NULL OR [Column] = @value然而,這(可能)在生產數據庫中是一件可怕的事情,因為(即使到 2021 年)我不知道任何主要RDMBS 正確處理了這種情況,你最終會得到非常非常糟糕的執行計划。

在您的情況下,請執行以下操作:

String sql;
List<MySqlParameter> parameters = new List<MySqlParameter>();

{
    StringBuilder sb = new StringBuilder( "SELECT columnA, columnB, FROM table" ).AppendLine();
    
    List<String> predicates = new List<String>();
    if( valueA != null )
    {
        predicates.Add( "columnA = @pA" );
        parameters.Add( new MySqlParameter( "@pA", valueA ) );
    }

    if( valueB != null )
    {
        predicates.Add( "columnB = @pB" );
        parameters.Add( new MySqlParameter( "@pB", valueB ) );
    }

    // etc
    
    if( predicates.Count > 0 )
    {
        _ = sb.AppendLine( "WHERE" );
        _ = sb.AppendLine( String.Join( " AND ", predicates ) );
    }

    //

    _ = sb.AppendLine( "ORDER BY foo GROUP BY bar LIMIT 0, 100" );

    sql = sb.ToString();
}

using( var cmd = new MySqlCommand( sql, connection ) )
{
    cmd.Parameters.AddRange( parameters );

    cmd.Execute...
}

您可以使用簡單的OR邏輯,並且在 C# 端檢查空格更容易

注意使用參數化防止SQL注入

請注意使用多行字符串使查詢更易於閱讀

const string query = @"
SELECT columnA, MAX(columnB) etc
FROM table
WHERE (columnA = @valueA OR @valueA IS NULL)
  AND (columnB = @valueB OR @valueB IS NULL)
GROUP BY columnA
LIMIT 0, 100;
";
using (var cmd = new MySqlCommand(query, connection))
{
    cmd.Parameters.AddWithValue("@valueA", string.IsNullOrWhiteSpace(valueA) ? (object)DBNull.Value : valueA);
    cmd.Parameters.AddWithValue("@valueB", string.IsNullOrWhiteSpace(valueB) ? (object)DBNull.Value : valueB);

大型表的性能可能不是很好,因此您可能需要使用完全獨立的查詢

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM