-1

在我们的 Oracle 数据库中,我有一个表(比如 MYTABLE),其中列 VALUE_NUMBER 类型为 NUMBER(NULL,未指定精度)。此表包含一个值1178.2

当使用标准 ADO.Net(实际上是 ODP.Net)从该列中检索数据,然后将十进制值转换为字符串时,我得到“1178.20”。显然,将常量转换1178.2M为字符串时,输出为1178.2.

深入挖掘,我查看了 decimal.GetBits() 的输出,结果证明是不同的,尽管在比较两个数字时它们确实被认为是相等的。

下面的代码示例说明了这种行为:

using (var connection = new OracleConnection("my connection string"))
{
    connection.Open();
    var command = connection.CreateCommand();
    command.CommandText = "SELECT VALUE_NUMBER FROM MYTABLE";
    command.CommandType = CommandType.Text;
    using (command)
    {
        var reader = command.ExecuteReader(CommandBehavior.Default);
        reader.Read();
        decimal oracleDecimal = reader.GetDecimal(reader.GetOrdinal("VALUE_NUMBER"));
        Console.WriteLine(oracleDecimal); // output: 1178.20 (NOT expected)
        var bitsFromOracle = decimal.GetBits(oracleDecimal).Select(x => x.ToString());
        var bitsFromOracleString = string.Join(",", bitsFromOracle.ToArray());
        Console.WriteLine(bitsFromOracleString); // 117820,0,0,131072

        // sanity check
        const decimal constantDecimal = 1178.2M;
        Console.WriteLine(constantDecimal); // output: 1178.2 (expected)
        var bitsFromConstant = decimal.GetBits(constantDecimal).Select(x => x.ToString());
        var bitsFromConstantString = string.Join(",", bitsFromConstant.ToArray());
        Console.WriteLine(bitsFromConstantString); // 11782,0,0,65536

        Console.WriteLine(oracleDecimal == constantDecimal); // True 
    }
}

这应该如何解释?

下面是表 CREATE & INSERT 脚本来完成这项工作:

CREATE TABLE MYTABLE (
  ID  NUMBER(10)             NOT NULL,
  VALUE_NUMBER           NUMBER
);

INSERT INTO MYTABLE(ID,VALUE_NUMBER) VALUES(1,1178.2);

更新:

@Vash 的回答和他随后的评论得出了正确的结论,即 .Net 十进制类型实际上包含有关其位数的信息,即使它们与相等性无关。1178.2M1178.20M因此具有不同的位表示,尽管.Equals()方法和==运算符显然认为这些数字相等。

4

3 回答 3

1

您遇到的主要问题是您没有对从数据库收到的行数据应用任何格式。

如果你想有特定的格式,你应该指定它。在文档中,您将找到Formatting Types,其中包含如何处理格式的所有信息。

如果你只想有结果

Console.WriteLine(valueNumber.ToString("N1", CultureInfo.InvariantCulture));
于 2012-08-09T16:35:39.640 回答
0

这会导致显示问题或计算问题吗?

如果您只想根据需要显示输出,您可以使用valueNumber.ToString("G")?

于 2012-08-09T16:34:14.057 回答
-1

你不能。如果您想这样做,您必须将其转换为字符串。

select 1123.80 num from dual;

select to_char(1123.80, 9999.99) from dual;

即唯一的方法是

SQL> INSERT INTO MYTABLE(ID,VALUE_NUMBER) VALUES(1,1178.20);
SQL> SELECT to_char(VALUE_NUMBER, 9999.99) NUM FROM MYTABLE

NUM
-------------------
1178.20 (string/varchar)

SQL> SELECT VALUE_NUMBER NUM FROM MYTABLE

NUM
-------------------
1178.2 (number)

这可能会在稍后对值执行数字(十进制)操作时导致问题,因为它变成了string并且需要number再次转换/强制转换,这不是一个非常推荐的方式。即使您不关心精度是NUMBER(10,2)from NUMBER(10),结果也将是相同的。

于 2012-08-09T16:21:23.417 回答