2015-08-20 25 views
4

代碼:.NET:如何處理SQL查詢中可能的空值?

private void DoSomethingWithDatabase(string f1, int f2) 
{ 
    SqlCommand myCommand = new SqlCommand("SELECT Field1,Field2,Field3 FROM MyTable WHERE Field1 = @F1 AND Field2 = @F2", this.myConn); 
    myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar); 
    myCommand.Parameters.Add("@F2", System.Data.SqlDbType.Int); 

    if (f1 == "") 
     myCommand.Parameters["@F1"].Value = DBNull.Value; 
    else 
     myCommand.Parameters["@F1"].Value = f1; 

    if (f2 < 0) 
     myCommand.Parameters["@F2"].Value = DBNull.Value; 
    else 
     myCommand.Parameters["@F2"].Value = f2; 

    // code to do stuff with the results here 
} 

的服務器是Microsoft SQL Server實例。

數據庫表MyTable包含可爲空的字段。因此,null是執行查詢時搜索的有效值。

從我的閱讀中,也從類似這樣的測試代碼中,執行像我在這裏所做的一樣工作不正常,因爲顯然你不能這樣做一個「等於null」的比較 - 你應該這樣做「一片空白」。

看起來您可以通過將ANSI_NULL設置爲OFF(根據https://msdn.microsoft.com/en-us/library/ms188048.aspx)來更正此問題並使其工作,但它也表示此方法已被棄用且不應使用。

該文章建議您可以使用OR運算符來執行類似WHERE Field1 = 25 OR Field1 IS NULL的操作。問題是,通過一次調用這個函數,我想檢查或者是 null並且只有null,或者對於給定的常量值,沒有別的。

到目前爲止,似乎我需要基本上逐個字符串地構建查詢,以解釋NULL值的可能性。所以我需要做這樣的事情:

string theQuery = "SELECT Field1,Field2,Field3 FROM MyTable WHERE "; 
if (f1 == "") 
    theQuery += "Field1 IS NULL "; 
else 
    theQuery += "Field1 = @F1 "; 

// ... 

SqlCommand myCommand = new SqlCommand(theQuery, this.myConn); 
if (f1 == "") 
{ 
    myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar); 
    myCommand.Parameters["@F1"].Value = f1; 
} 

// ... 

這是真的需要怎麼做?有沒有更有效的方法來做到這一點,而不重複if塊,並通過使用參數,而不是連接在一起查詢字符串?這個例子中的空字符串被轉換爲NULL,在實際使用的場景中,空字符串不會被使用,而是存儲NULL,數據庫不在我的控制之下,所以我不能只是說「把所有的NULL改爲空字符串」。對於整數也是一樣 - 如果我們將-1傳遞給函數,它應該測試一個空值。壞習慣?也許,但數據庫本身不在我的控制之下,只有訪問它的代碼是)。

+1

請謹慎對待WHERE子句中的ISNULL或COALESCE。您可能希望創建一個索引以加快查詢速度(類似Field1,Field2 INCLUDE Field3),ISNULL/COALESCE將停止正在使用的索引。你在最終代碼塊中的建議看起來很好,我認爲比任何給定的答案都好。 –

回答

2

string theQuery = "SELECT Field1, Field2, Field3 FROM MyTable WHERE ISNULL(Field1,'') = @F1"; 

通過這種方式,您可以擺脫if塊,並將空值解釋爲空字符串,如您的f1變量。

+0

所以我會做'SELECT ISNULL(Field1,'')作爲Field1 FROM MyTable WHERE Field1 = @ F1'?然後,如果我給F1參數分配了一個空字符串,它會評估爲真?如果是這樣,這聽起來像它正是我需要的......! – fdmillion

+0

但這樣查詢將不會返回字段爲空的行。那是你想要的嗎? –

+0

@MartínMisol爲什麼? – Kabulan0lak

1

SQL Server具有一個名爲ISNULL(Column,Value)的函數,您可以在其中指定一列來檢查並設置默認值,以防此列爲NULL。 您爲什麼不使用檢查here

+0

您的鏈接轉到巴西葡萄牙語版本的文檔。 en-us版本是https://msdn.microsoft.com/zh-cn/library/ms184325(v=SQL.120).aspx –

+0

沒錯!謝謝安迪! –

0

如果你想避免,如果塊,你也許可以更改查詢弄成這個樣子:

SELECT Field1,Field2,Field3 FROM MyTable 
WHERE COALESCE(Field1,'') = @F1 AND COALESCE(Field2,-1) = @F2 
0

你可以做類似

WHERE ISNULL(Field, '') = @F1 

在這種情況下,NULL字段被視爲空字符串。另一種方法是:

WHERE Field IS NULL OR Field = @1 
0

你處理NULL的方式是正確的。也許你可以使用一個輔助方法,像這樣的:

private string AppendParameter(string query, string parameterName, string parameterValue, SqlParameterCollection parameters) 
{ 
    if (string.IsNullOrEmpty(parameterValue)) 
     query += "Field1 IS NULL "; 
    else 
    { 
     query += "Field1 = " + parameterName + " "; 
     parameters.AddWithValue(parameterName, parameterValue); 
    } 

    return query; 
} 
0
SqlCommand myCommand = new SqlCommand(@"SELECT Field1,Field2,Field3 
    FROM MyTable 
    WHERE 
    ((@F1 IS NULL AND [field1] IS NULL) OR [field1] = @F1) AND 
    ((@F2 IS NULL AND [field2] IS NULL) OR [field2] = @F2);", this.myconn); 
    myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar).Value = DBNull.Value; 
    myCommand.Parameters.Add("@F2", System.Data.SqlDbType.Int).Value = DBNull.Value; 


    if (!string.IsNullOrEmpty(f1)) 
     myCommand.Parameters["@F1"].Value = f1; 
    if (f2 != -1) 
     myCommand.Parameters["@F2"].Value = f2; 

這將利用關於字段的索引。