为什么IS NULL有效,但DateTime的DBNull.Value的SQL参数却不起作用?

时间:2018-10-03 14:52:22

标签: c# datetime sqlcommand dbnull sqlparameters

我有一个C#控制台应用程序,该应用程序正在SQL Server 2014上执行数据库查找。它对带有名为有效日期的DateTime列的表进行查询,该列允许空值。

如果我编写使用“ WHERE EffectiveDate IS NULL”的标准SQL查询,结果将正确返回。如果我更改WHERE子句以接受参数并将该参数设置为DBNull.Value,则结果为null。

示例1使用IS NULL-> resultObj具有适当的值:

    public void RetrieveFileType()
    {
        string sSQL = "SELECT [FileType]  " +
                      "FROM DTCC_APP_ProcessControl " +
                      "WHERE [EffectiveDate] IS NULL ";

        using (SqlConnection oConn = GetNewConnection())
        {
            using (SqlCommand cmd = new SqlCommand(sSQL, oConn))
            {
                object resultObj = cmd.ExecuteScalar();
            }
        }
    }

示例2使用DBNull.Value-> resultObj = null:

    public void RetrieveFileType()
    {
        string sSQL = "SELECT [FileType]  " +
                      "FROM DTCC_APP_ProcessControl " +
                      "WHERE [EffectiveDate] = @EffectiveDate";

        using (SqlConnection oConn = GetNewConnection())
        {
            using (SqlCommand cmd = new SqlCommand(sSQL, oConn))
            {
                cmd.Parameters.AddWithValue("@EffectiveDate", DBNull.Value);

                object resultObj = cmd.ExecuteScalar();
            }
        }
    }

我也尝试过:

cmd.Parameters.Add("@EffectiveDate", SqlDbType.DateTime).Value = DBNull.Value;

cmd.Parameters.AddWithValue("@EffectiveDate", SqlDateTime.Null);

我唯一得到结果的是是否使用IS NULL。这是一个简化的示例,我可以选择为@EffectiveDate设置一个值或Null。

我已经阅读了其他在线信息,似乎我需要的只是一个可为空的数据库列,并使用DBNull.Value作为参数,它应该可以工作。我想念什么?

2 个答案:

答案 0 :(得分:2)

问题与参数化无关,但与参数可以具有NULL值这一事实无关。就像 Steve 所说的那样,您不能直接将NULLNULL进行比较,否则它将不会返回任何内容(根据SQL标准,它始终为false)。 / p>

当参数被保证从不为NULL时,示例2中的直接比较效果很好,如果示例1始终为NULL,则示例1很好。但是,如果根据某些外部条件有可能出现NULL或不出现SELECT [FileType] FROM DTCC_APP_ProcessControl WHERE [EffectiveDate] = @EffectiveDate OR @EffectiveDate IS NULL 的情况,我们也必须考虑将其纳入SQL查询。这样的事情会做:

EffectiveDate

这可以同时处理两种情况,但是请注意,此表达式不可SARGable,并且如果有Sub OptimizeCode_Begin() Application.ScreenUpdating = False Application.EnableEvents = False Application.Calculation = xlCalculationManual ActiveSheet.DisplayPageBreaks = False End Sub _____ Sub OptimizeCode_End() ActiveSheet.DisplayPageBreaks = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True Application.ScreenUpdating = True End Sub ______ Sub GetFromOutlook() Dim OutlookApp As Outlook.Application Dim OutlookNamespace As Namespace Dim Folder As MAPIFolder Dim OutlookMail As Variant Dim i As Long Dim j As Long Call OptimizeCode_Begin Set OutlookApp = New Outlook.Application Set OutlookNamespace = OutlookApp.GetNamespace("MAPI") Set Folder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("Individual Lot Inspections") Set Folder2 = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("Construction Site Inspections") i = 1 For Each OutlookMail In Folder.Items If OutlookMail.ReceivedTime >= Range("From_date").Value Then Range("eMail_subject").Offset(i, 0).Value = OutlookMail.Subject Range("eMail_date").Offset(i, 0).Value = OutlookMail.ReceivedTime Range("eMail_sender").Offset(i, 0).Value = OutlookMail.SenderName ' Range("eMail_text").Offset(i, 0).Value = OutlookMail.Body i = i + 1 End If Next OutlookMail j = i + 1 For Each OutlookMail In Folder2.Items If OutlookMail.ReceivedTime >= Range("From_date").Value Then Range("eMail_subject").Offset(j, 0).Value = OutlookMail.Subject Range("eMail_date").Offset(j, 0).Value = OutlookMail.ReceivedTime Range("eMail_sender").Offset(j, 0).Value = OutlookMail.SenderName j = j + 1 End If Next OutlookMail Set Folder = Nothing Set Folder2 = Nothing Set OutlookNamespace = Nothing Set OutlookApp = Nothing Call OptimizeCode_End 列,则不会使用索引。

另一种方法是,根据参数的最终值,客户端选择动态地在示例1或2之间进行选择,以提交一个或另一个查询。这可能会导致更好的性能和索引使用率。

答案 1 :(得分:1)

因为DB中的NULL与c#不同。

NULL = NULL在Sql中返回false。您必须使用IS NULL进行比较