【问题标题】:Storing .NET double value in Oracle DB在 Oracle DB 中存储 .NET 双精度值
【发布时间】:2011-04-15 19:06:47
【问题描述】:

我正在使用 ODP.NET 从 C# .NET 访问 Oracle DB。 请看以下代码:

  OracleConnection con = new OracleConnection();
  con.ConnectionString = "User Id=user;Password=pass;Data Source=localhost/orcl";
  con.Open();

  /* create table */
  DbCommand command = con.CreateCommand();
  command.CommandType = CommandType.Text;

  try
  {
    command.CommandText = "DROP TABLE TEST";
    command.ExecuteNonQuery();
  }
  catch
  {
  }

  //command.CommandText = "CREATE TABLE TEST (VALUE BINARY_DOUBLE)";
  command.CommandText = "CREATE TABLE TEST (VALUE FLOAT(126))";
  command.ExecuteNonQuery();

  /* now insert something */
  double val = 0.8414709848078965;
  command.CommandText = "INSERT INTO TEST VALUES (" + val.ToString(System.Globalization.CultureInfo.InvariantCulture) + ")";
  command.ExecuteNonQuery();

  /* and now read inserted value */
  command.CommandText = "SELECT * FROM TEST";
  DbDataReader reader = command.ExecuteReader();

  reader.Read();
  double res = (double) (decimal)reader[0];

  Console.WriteLine("Inserted " + val + " selected " + res);

由此产生的输出始终是: 插入 0,841470984807897 选择 0,841470984807897

但是在调试器下查看变量值 val == 0.8414709848078965 res == 0,841470984807897

为什么 res 被四舍五入?

我查看了 DB 并存储了四舍五入的值。

另一方面,我使用 Oracle SQL Developer 修改了这个值,我可以在数据库中存储 0.8414709848078965 吗?

我尝试了类型 NUMBER、FLOAT(126)、BINARY_DOUBLE... 总是相同的结果。

为什么使用 ODP.NET 会出现问题?

【问题讨论】:

    标签: oracle types double sqldatatypes


    【解决方案1】:

    好的,我发现如果参数类型是OracleDbType.BinaryDouble,它可以工作。但这会导致我的代码依赖于 ODP.NET。我想使用 ADO.NET 类型 (DbType) 来实现我的代码独立性。

    【讨论】:

      【解决方案2】:

      Oracle 实际上比 .net 具有更高的数字精度!
      我在直接 Oracle 中尝试过,效果很好,我建议更改为使用参数

      例如

      -- CREATE TABLE TEST (VALUE NUMBER(38,38)); (initial test)
      
      INSERT INTO TEST VALUES (0.8414709848078965);
      
      SELECT * FROM TEST;
      VALUE                  
      ---------------------- 
      0.8414709848078965 
      
      (recommendation)
      OracleParameter param = cmd.CreateParameter();  
      param.ParameterName = "NUMBERVALUE";  
      param.Direction = ParameterDirection.Input;  
      param.OracleDbType = OracleDbType.Decimal;  
      param.Value = "0.8414709848078965";  
      command.Parameters.Add(param); 
      

      【讨论】:

      • @tanging 的推荐。实际上我没有提到,我是通过 ado.net 接口使用它,而不是直接通过 oracle if。所以没有OracleDbType.Decimal。我只能使用 DbType.Double。 @using 参数 - 是的,当然它是在实际程序中以这种方式完成的。这里我只提供了简化的例子。参数不能解决问题。
      猜你喜欢
      • 1970-01-01
      • 2012-04-15
      • 2011-08-05
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 2018-11-12
      • 2016-08-17
      相关资源
      最近更新 更多