使用带有Null的WHERE子句的SQL Server参数化查询

时间:2014-11-14 22:53:35

标签: sql-server null where-clause parameterized-query

VB.NET 2012,ADO.NET,SQL Server 2014

我设置了一个运行良好的参数化查询。我基本上从DataTable读取来自与我的SQL Server不同的来源的记录。它足够小,我选择按记录读取记录并构建查询并点击SQL Server进行匹配。

但是当我的一个字段应该与null匹配时,我无法获得匹配。我知道存在一条记录,因为我可以直接在SQL Server中查看它并查看它。使用我的参数化查询不知何故,null被翻译得不正确。我尝试用@EngSerialNo手动替换参数DBNull.Value,但仍然无法正常工作。几乎看起来我需要两个不同的查询,具体取决于我的DataTable值是否为空。

sqQry.AppendLine("SELECT CityCode,CarNum,RegNum,Event,EngSerialNum)")
sqQry.AppendLine("FROM [MyDB].[dbo].[Events]")
sqQry.AppendLine("WHERE (CityCode=@City AND CarNum=@CarNo AND RegNum=@RegNo AND Event=@Event AND EngSerialNum=@EngSerialNo)") 'this looks for a value in EngSerialNo
'sqQry.AppendLine("WHERE (CityCode=@City AND CarNum=@CarNo AND RegNum=@RegNo AND Event=@Event AND EngSerialNum IS NULL)")     'this looks for a Null in EngSerialNo     

 Dim cmd As New SqlCommand

 With cmd
        .Connection = connMyDb
        .CommandType = CommandType.Text
        .CommandText = sqQry.ToString

         'cycle through each DataRow in the DataTable and check for returns
         Dim total As Integer = 0
         For Each row As DataRow In dtMain.Rows
             .Parameters.Clear()
             .Parameters.AddWithValue("@City", row.Item("City"))
             .Parameters.AddWithValue("@CarNo", row.Item("CarNo"))
             .Parameters.AddWithValue("@RegNo", row.Item("RegNo"))
             .Parameters.AddWithValue("@Event", row.Item("Event"))
             .Parameters.AddWithValue("@EngSerialNo", row.Item("EngSerialNo")) 'how do I get this to look for a null value when the DataTable contains a null value?

             Dim rowsAffected As Integer = .ExecuteNonQuery()
             total += rowsAffected
         Next row
End With

更新:我最终为每个DataRow创建了一个动态SQL。基本上对于每个DataRow,我检查关键字段是否为NULL或实际值,并创建适当的SQL命令文本。我有4个字段可以包含NULL但为了简单起见我只在这里演示了一个。我认为开发人员可以按照示例创建自己的查询。

 Dim cmd As New SqlCommand
 With cmd
        .Connection = connMyDb
        .CommandType = CommandType.Text

         'cycle through each DataRow in the DataTable and check for returns
         Dim total As Integer = 0
         For Each row As DataRow In dtMain.Rows
             .CommandText = BuildSql(row)

             .Parameters.Clear()
             .Parameters.AddWithValue("@City", row.Item("City"))
             .Parameters.AddWithValue("@CarNo", row.Item("CarNo"))
             .Parameters.AddWithValue("@RegNo", row.Item("RegNo"))
             .Parameters.AddWithValue("@Event", row.Item("Event"))
             .Parameters.AddWithValue("@EngSerialNo", row.Item("EngSerialNo")) 

             Dim rowsAffected As Integer = .ExecuteNonQuery()
             total += rowsAffected
         Next row
End With

Private Function BuildSql(ByVal dr As DataRow) As String
     Dim sqQry As New StringBuilder
     sqQry.AppendLine("SELECT CityCode,CarNum,RegNum,Event,EngSerialNum)")
     sqQry.AppendLine("FROM [MyDB].[dbo].[Events]")

     If dr.Item("EngSerialNo") Is DBNull.Value Then
        sqQry.AppendLine("WHERE (CityCode=@City AND CarNum=@CarNo AND RegNum=@RegNo AND Event=@Event AND EngSerialNum IS NULL)")     'this looks for a Null in EngSerialNo            
     Else
        sqQry.AppendLine("WHERE (CityCode=@City AND CarNum=@CarNo AND RegNum=@RegNo AND Event=@Event AND EngSerialNum=@EngSerialNo)") 'this looks for a value in EngSerialNo
     End If

     Return sqQry.ToString
End Function

1 个答案:

答案 0 :(得分:3)

在SQL中,您无法比较空值,即EngSerialNum = null始终求值为false,即使字段中的值为空。

您可以动态创建查询,以便使用is null匹配空值,也可以使用如下表达式:

((EngSerialNum is null and @EngSerialNo is null) or EngSerialNum = @EngSerialNo)