为什么 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 在你不能直接比较 NULL
和 NULL
之前所说的那样,否则它不会 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之间动态选择。这可能会带来更好的性能和索引使用。
我有一个 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 在你不能直接比较 NULL
和 NULL
之前所说的那样,否则它不会 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之间动态选择。这可能会带来更好的性能和索引使用。