选择行WHERE column = value或column为null(当前解决方案是草率和慢)

时间:2016-08-18 20:30:49

标签: c# sql

我目前正在开发Inserts customer data into a database的网络表单。在插入之前,数据库需要是queried for duplicates。我检查的字段是Name, Shipping Address, and Billing AddressNamerequired field,至少one address is also required。现在我的(非常混乱)代码看起来像这样:

string partialQuery;
SqlConnection sqlConn = new SqlConnection(connString);

if(/*both addresses fillied out*/)  {
    partialQuery = "BillingAddress=@BillingAddress AND ShippingAddress=@ShippingAddress";
}
else if(/*only billing address is filled out*/)  {
    partialQuery = "BillingAddress=@BillingAddress AND ShippingAddress IS NULL";
}
else if(/*only shipping address is filled out*/)  {
    partialQuery = "BillingAddress IS NULL AND ShippingAddress=@ShippingAddress";
}
else  {  throw new Exception("error...");  }

SqlCommand cmd = new SqlCommand("SELECT * FROM Customers WHERE Name=@Name AND " + partalQuery, sqlConn);

cmd.Parameters.AddWithValue("@Name", Name.Text);
cmd.Parameters.AddWithValue("@BillingAddress", BillingAddress.Text, null);
cmd.Parameters.AddWithValue("@ShippingAddress", ShippingAddress.Text, null);

我一直在尝试使用一个SQL命令找到一种更有效的方法,我认为这段代码会这样做:

SELECT * 
FROM Customers 
 WHERE Name = @Name
 AND BillingAccount = ISNULL(@BillingAccount, BillingAccount)
 AND ShippingAccount = ISNULL(@ShippingAccount, ShippingAccount)

我们的想法是检查@BillingAccount / @ShippingAccount是否为空,如果是,则表达式将评估为BillingAccount = BillingAccount / ShippingAccount = ShippingAccount(然后评估为true)。

我遇到的问题是,当 value = value 为true时, null = null 为false ,使整个WHERE子句为假(因为我使用AND)。

我不确定从哪里听到。

旁注:如果您想知道为什么我的AddWithValue方法使用3个参数,它是一个将c#空值转换为SQL空值的扩展方法。如果您有兴趣,可以听取代码:http://www.codeproject.com/Tips/310792/Handling-null-values-in-SqlParameter-parameter-obj

5 个答案:

答案 0 :(得分:2)

在两侧使用IsNull

  WHERE Name = @Name
    AND IsNull(BillingAccount, -1) = 
            Coalesce(@BillingAccount, BillingAccount, -1)
    AND IsNull(ShippingAccount, -1)  =
            Coalesce(@ShippingAccount, ShippingAccount, -1)

或者包括检查参数和字段是否都为空

   WHERE Name = @Name
    AND (Coalesce(@BillingAccount, BillingAccount) is Null Or
       BillingAccount = Coalesce(@BillingAccount, BillingAccount, -1))
    AND Coalesce(@ShippingAccount, ShippingAccount) is Null Or
       ShippingAccount = Coalesce(@ShippingAccount, ShippingAccount)

答案 1 :(得分:1)

防止重复注册的一种方法:


INSERT INTO Customers ( CustomerId )
   SELECT 1 AS CustomerId 
    WHERE NOT EXISTS 
      ( SELECT 1 FROM Customers WHERE CustomerId = 1 );

避免null = null的一种方法是false


 SELECT * 
       FROM Customers 
      WHERE Name = @Name
        AND ISNULL(BillingAccount, '_') = ISNULL(@BillingAccount, '_')
        AND ISNULL(ShippingAccount, '_') = ISNULL(@ShippingAccount, '_')

答案 2 :(得分:1)

另一种方式

 WHERE Name = @Name
 AND ( BillingAccount = @BillingAccount or  @BillingAccount is null )
 AND ( ShippingAccount = @ShippingAccount or  @ShippingAccount is null)

根据您的评论

where Name = @Name
and(
(BillingAccount = @BillingAccount and ShippingAccount = @ShippingAccount)or
(@BillingAccount is null and @ShippingAccount is null)
)

答案 3 :(得分:0)

你能试试吗?


 SELECT * 
       FROM Customers 
      WHERE Name = @Name
        AND ISNULL(BillingAccount, '_') = ISNULL(@BillingAccount, ISNULL(BillingAccount, '_'))
        AND ISNULL(ShippingAccount, '_') = ISNULL(@ShippingAccount, ISNULL(ShippingAccount, '_'))

答案 4 :(得分:-1)

为什么COALESCE优于ISNULL

的一个例子
...
PpComboItem := (TPpListBoxItem(Designer.CreateComponent(TPpListBoxItem, PpCombo, 10, 10, 100, 100)));
PpComboItem.Parent := PpCombo;
Designer.Modified;
...