为什么 IS NULL 有效但 SQL Parameter with DBNull.Value for DateTime 无效?

Why does IS NULL work but SQL Parameter with DBNull.Value for DateTime does not?

我有一个 C# 控制台应用程序,它正在 SQL Server 2014 上执行数据库查找。它查询 table 具有名为 EffectiveDate 的 DateTime 列,它允许空值。

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

示例 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 作为参数,它应该可以工作。我错过了什么?

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

NULL = NULL returns 在 Sql 中为假。你必须使用IS NULL来比较

问题与参数化无关,但与参数可以具有 NULL 值这一事实有关。就像 Steve 在你不能直接比较 NULLNULL 之前所说的那样,否则它不会 return 任何东西(它总是评估为 false到 SQL 标准)。

当保证参数永远不会是 NULL 时,示例 2 中的直接比较效果很好,如果它始终是 NULL,则示例 1 很好。但是,如果根据某些外部条件它有可能是 NULL 或不是,我们也必须将其考虑到 SQL 查询中。这样的事情会做:

SELECT [FileType]
FROM DTCC_APP_ProcessControl
WHERE [EffectiveDate] = @EffectiveDate OR @EffectiveDate IS NULL

这会处理这两种情况,但是请注意,此表达式不可 SARGable,并且不会在 EffectiveDate 列上使用索引(如果有的话)。

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