【问题标题】:JDBC SQL Server Decimal "invented" precisionJDBC SQL Server 十进制“发明”精度
【发布时间】:2018-08-10 22:02:34
【问题描述】:

注意:这可能与 SQL Server、Oracle、DB2 或 MySQL 数据库一起运行。但是对于这个例子,我只是使用 SQL Server。该解决方案需要足够通用,才能应用所有提到的数据库。

在 SQL Server 中,我有一个定义为 decimal(32, 16) 的列,因为该列必须能够存储潜在的大值或精确值。但是,它也可能存储小的或不精确的值。但是当我选择 BigDecimal 时,它会返回原始中没有的尾随零。我认为这是因为我的列定义允许高精度。

我不希望以“发明”的比例/精度来存储或返回任何值,但我仍然需要考虑那么大的比例/精度。

// ... set up ... 
// precision 2, scale 2
BigDecimal bdInsert = new BigDecimal("0.51");
preparedStatement.insertBigDecimal(1, bdInsert);
// ... insert/commit ... select ...
// precision 0, scale 16 <-- Grrrrrrr!
BigDecimal bdResult = resultSet.getBigDecimal(1);
System.out.println(bdResult);
// prints "0.5100000000000000" <-- Grrrrrrr!

SQL Server 是否不存储或 JDBC 不发送也不选择插入的 BigDecimal 的精度和小数位数?

我不能只截断零,因为 BigDecimal 可能存储有尾随零以表明它是精确的。

// "0.510000" indicating that this value is accurate to the 6th place
BigDecimal bdPrecise = new BigDecimal("0.510000");
preparedStatement.insertBigDecimal(1, bdPrecise);

// precision 0, scale 16 
BigDecimal bdResult = resultSet.getBigDecimal(1);

System.out.println(bdResult);
// prints "0.5100000000000000" loses information

System.out.println(bdResult.stripTrailingZeros());
// prints "0.51", loses information

// What I want is "0.510000"

有没有办法通过 SQL Server 或 JDBC 获得原始 BigDecimal 的比例/精度?

请不要告诉我,我必须创建一个单独的列来存储这些信息...

我想另一种方法是仅将 BigDecimals 插入/选择为字符串,然后从字符串中解析它,例如 new BigDecimal(val)。但我更喜欢存储为小数。

谢谢。

【问题讨论】:

  • 您是否考虑过使用sql_variant 列?
  • @HABO 看起来很有趣。但是,我忘了提到此代码可用于多种数据库,并且该解决方案应该足够通用,以便能够跨 SQL Server、Oracle、DB2 或 MySQL 数据库工作。 (所以主要是 ANSI SQL) 我知道这很受限制。更新问题以包含此要求。
  • 几年前也有过类似的情况,精度不同,也可以作为指标。这有点 hack,但我将值存储为 VARCHAR,因此 0.510000 与尾随零一起存储
  • @JohnCappelletti 是的.. 那是我的替代想法。他们不存储原始比例/精度真是太可惜了
  • 根据定义,decimal(32, 16) 的比例为 16,因此 SQL 标准可以预期甚至要求该行为。对于 DB2,您可能希望改用 DECFLOAT(它在 SQL:2016 中指定,但据我所知,目前仅在 DB2 中受支持)。

标签: java sql-server tsql jdbc bigdecimal


【解决方案1】:

以下代码演示了 SQL Server 中的 sql_variant 数据类型。 (以及如何显示有关表达式的数据类型信息。)由于该解决方案需要应用于任何能够保存位的事物,因此它不会解决您的所有问题,但它可能具有一定的价值。

我怀疑唯一可以跨“所有”平台工作的解决方案是一个字符串,可能包含具有明确精度的 XML。

declare @Samples as Table ( Value sql_variant );
insert into @Samples ( Value ) values
  ( Cast( 3.14 as Decimal( 10, 2 ) ) );
insert into @Samples ( Value ) values
  ( Cast( 3.14 as Decimal( 10, 3 ) ) );
insert into @Samples ( Value ) values
  ( Cast( 3.14 as Decimal( 10, 4 ) ) );
insert into @Samples ( Value ) values
  -- NB: Both values are inserted with scale 5 when they are included in a single INSERT.
  ( Cast( 42 as Decimal( 10, 1 ) ) ),
  ( Cast( 42 as Decimal( 10, 5 ) ) );
insert into @Samples ( Value ) values
  ( Cast( 1.618 as Decimal( 10, 6 ) ) );
insert into @Samples ( Value ) values
  ( 'Edgar' );

select Value, SQL_Variant_Property( Value, 'BaseType' ) as BaseType,
  SQL_Variant_Property( Value, 'Precision' ) as Precision,
  SQL_Variant_Property( Value, 'Scale' ) as Scale
  from @Samples;

(然后是钢厂,他们希望在英寸和十六分之一之间有一个点,例如 23 3/4 英寸显示为“23.12”。将“36.1”和“36.10”处理为输入时相差 9/16和输出?Oy。)

【讨论】:

  • 有趣的东西,希望对看到这个的其他人有用。我对此一无所知,因为我主要玩的是无聊的 ANSI Sql。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 2018-01-20
  • 1970-01-01
相关资源
最近更新 更多