OracleParameter 和 DBNull.Value

Posted

技术标签:

【中文标题】OracleParameter 和 DBNull.Value【英文标题】:OracleParameter and DBNull.Value 【发布时间】:2009-11-09 14:37:41 【问题描述】:

我们在 Oracle 数据库中有一个表,其中包含一个 Char(3 Byte) 类型的列。 现在我们使用参数化的 sql 来选择一些带有 DBNull.Value 的行,但它不起作用:

OracleCommand command = null;  
OracleDataReader dataReader = null;  

string sql = "select * from TEST_TABLE where COLUMN_1 = :COLUMN_1";  

try  
  
    OracleConnection connection = (OracleConnection) dbConnection;  
    command = new OracleCommand( sql, connection );  

    OracleParameter param_1 = new OracleParameter( "COLUMN_1", OracleDbType.Char );  
    command.Parameters.Add( param_1 );

    param_1.Value = DbNull.Value;

    dataReader = command.ExecuteReader( );

    int recordCount = 0;
    while( dataReader.Read( ) == true )
    
        recordCount++;
    

    Console.WriteLine( "Count = " + recordCount ); // is 0

[...]  

我错过了什么吗?我们肯定有一些包含 DBNull 的行, 但是你会用“is null”而不是“= null”编写一个“普通”sql的情况 也很明显。

有人可以解释这种行为吗?如何编写需要条件来检查 DBNull 的参数化 sql?

谢谢

【问题讨论】:

【参考方案1】:

Null 是没有被设置为任何东西,因此您不会通过 '= null' 获得正确的行为。因为 null 是没有值,所以说“这个没有任何值的变量与这个没有任何值的变量具有相同的值”是没有意义的。如果你没有价值,你就不能拥有与其他东西相同的价值。

解决这个问题的一种方法是创建两个 sql 语句,一个接受参数,另一个带有“is null”。然后使用“if”语句来选择使用哪一个。

声明 1:

string sql = "select * from TEST_TABLE where COLUMN_1 = :COLUMN_1  

语句 2:

string sql = "select * from TEST_TABLE where COLUMN_1 is null

除非您总是与 null 进行比较。然后,只需使用语句 2

【讨论】:

执行此操作时,请注意 Oracle 不会索引空值,可能会导致查询计划效率低下 我担心我不得不这样做,你刚刚证实了我的怀疑。这真的很笨拙。我希望有更好的方法...【参考方案2】:

在这种情况下你必须使用IS NULL:

string sql = "select * from TEST_TABLE where COLUMN_1 is null";

在 SQL 中与空值进行任何比较将始终产生unknown 结果,这意味着您不会得到任何返回的行。

【讨论】:

【参考方案3】:

你可以这样做:

select *
from   TEST_TABLE
where  (COLUMN_1 = :COLUMN_1 and :COLUMN_1 Is Not Null) Or 
       (COLUMN_1 Is Null     and :COLUMN_1 Is Null)

【讨论】:

使用 'command.BindByName = true' 避免绑定 3 个具有相同值的参数。 ***.com/questions/1422032/…【参考方案4】:

像这样修改你的代码:

OracleCommand command = null;  
OracleDataReader dataReader = null;  

string sql = "select * from TEST_TABLE where COLUMN_1 IS NULL"

try  
  
    OracleConnection connection = (OracleConnection) dbConnection;  
    command = new OracleCommand( sql, connection );  

    dataReader = command.ExecuteReader( );

    int recordCount = 0;
    while( dataReader.Read( ) == true )
    
        recordCount++;
    

    Console.WriteLine( "Count = " + recordCount ); // is 0

【讨论】:

【参考方案5】:
SELECT t1.*
  FROM t1, (SELECT :s v FROM dual) tmp
 WHERE t1.s = tmp.v OR (t1.s IS NULL AND tmp.v IS NULL)

这样也行。

【讨论】:

以上是关于OracleParameter 和 DBNull.Value的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL NVL 和 OracleParameter 在 C# 中不起作用

OracleParameter.Size 有啥影响?

如何从 OracleParameter 对象中获取值

c# OracleParameter 抛出 ORA-06502

将 OracleParameter.Value 转换为 Int32

OracleParameter 对象已包含在集合中