急:DB2 Decimal update时精度出现问题

sTigerwsk 2009-10-20 07:49:22
我有一张数据库表,表中有字段 aaa decimal(17,2).

在使用过程中出现如下问题:

在给字段赋值433.36后,打日志得到值是433.36。

在数据库update后,打日志得到值为433.35。

中间未做任何处理。

请问有何办法可以避免此类问题?

数据库版本为:DB2 9.5,程序为Proc的程序。

PS:该问题不是经常出现,在更新数据库100次后可能会出现一次。
...全文
1330 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
sTigerwsk 2010-01-01
  • 打赏
  • 举报
回复
DB2V9.7版本中不再会出现该问题……

据IBM人士解释……
sTigerwsk 2009-11-16
  • 打赏
  • 举报
回复
再次研究了一下,发现如果将一个C中的double类型不做四舍五入处理,直接交给数据库,多次更新后会出现精度问题……

今天又出了一个怪问题,0.01直接更新之后变成0了……
sTigerwsk 2009-11-03
  • 打赏
  • 举报
回复
DB2的对应字段直接建成double型字段?然后设置精度?
leonjava 2009-10-28
  • 打赏
  • 举报
回复
之前也遇到类似情况
把 DOUBLE 的精度加长 变为3位搞定
johdan_honey 2009-10-24
  • 打赏
  • 举报
回复
建议你把日志打印的数据的精度提高,按照你的情况必然是因为还有第三位小数造成的
ACMAIN_CHM 2009-10-23
  • 打赏
  • 举报
回复
[Quote]而且见到过db2插值进去后,值会变成一个高精度近似数,比如,2.13,插进去有可能会变成2.1299999999[/Quote]

首先我们先达成共识, 计算机中无法用8或或N个字节表示某个区间内所有的实数 . 而 2.13 你可以试着把它转换成 2进制。

所以在计算中如果有double的小数,会有误差。
但 decimal 本身应该没有, 所以需要看你是如何插入这个小数的,当然也要看你对这个字段的定义是什么? 是 deciaml(, 还是double 这也是为会要检查你的表结构。
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
上面说的那种情况是不指定decimal的精度有可能会出现。
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 acmain_chm 的回复:]
应该不是BUG,

建议贴出来你的表结构,以及你的插入语句。你的db2版一,这样其它人也可以试一下。
[/Quote]

大哥,这个跟表结构貌似没有关系。我的db2版本是9.5,这个问题在8系统列的版本上也出现过。

类似问题有人在chinaunix也发帖询问了。

而且见到过db2插值进去后,值会变成一个高精度近似数,比如,2.13,插进去有可能会变成2.1299999999
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 mr_bean 的回复:]
数据库一直都有类似问题 但是我碰到的只是存储奇数尾数才会出  现在能缓解方法是decimal转为double


[/Quote]

原来使用oracle数据库,没有发现类似问题,也可能是较少使用奇数尾数。
WWWWA 2009-10-23
  • 打赏
  • 举报
回复
用DOUBLE类型试试,如果没有问题,则是decimal的问题
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wwwwa 的回复:]
直接赋值没有经过计算,应该是BUG吧
[/Quote]

有经过一个计算,一个简单的减法计算。

原decimal字段的值是555988.36, 然后减去555555, 得到433.36,此处第一次打日志,打出来的日志为433.36。

然后进行update操作,操作前打日志,433.36,操作后需要查询结果插入别一张表中,查询后打日志,433.35……

且这个问题出现的频率确实不是很高,很偶然的出现……

精度?类型转换?decimal与double的差别?
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 acmain_chm 的回复:]
应该不是BUG,

建议贴出来你的表结构,以及你的插入语句。你的db2版一,这样其它人也可以试一下。
[/Quote]

这个跟表结构没有什么关系。

我用的是类似于insert into aaa (aa, bb, cc) values(11,22,33);

update时采用的是用游标打开获取当前记录,然后update current cursor的方式去更新。

很怀疑是proc的double与decimal的转换……
sTigerwsk 2009-10-23
  • 打赏
  • 举报
回复
在proc中连接两次打印出来的值都是对的,然后经过一次update操作后,再从数据库读出来,打日志值就差了0.01.

这个如果说proc的问题也是bd2,proc的问题吧,在oracle下没有遇到过这样的问题。

初步怀疑与decimal的存储方式有关。
Liyingyue_FFS 2009-10-23
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 acmain_chm 的回复:]
引用而且见到过db2插值进去后,值会变成一个高精度近似数,比如,2.13,插进去有可能会变成2.1299999999

首先我们先达成共识, 计算机中无法用8或或N个字节表示某个区间内所有的实数 . 而 2.13 你可以试着把它转换成 2进制。

所以在计算中如果有double的小数,会有误差。
但 decimal 本身应该没有, 所以需要看你是如何插入这个小数的,当然也要看你对这个字段的定义是什么? 是 deciaml(, 还是double 这也是为会要检查你的表结构。
[/Quote]

计算机中所有数据的存储都是2进制的,但是大多数小数部分存储时只能用一个指定长度范围内的近似的2进制序列来存储。因此,数据库存储的大多数小数数据只是我们所期望的值的近似值然后通过某种规则(四舍五入到某一位)来显示出我们需要的值。

这两个数据中存在某种误差,而你UPDATE操作的对象是数据库物理存储的数据,这样,在经历100次UPDATE之后,这个误差就可能由量变引起质变。
ACMAIN_CHM 2009-10-21
  • 打赏
  • 举报
回复
应该不是BUG,

建议贴出来你的表结构,以及你的插入语句。你的db2版一,这样其它人也可以试一下。
WWWWA 2009-10-21
  • 打赏
  • 举报
回复
直接赋值没有经过计算,应该是BUG吧
liyan93834183 2009-10-21
  • 打赏
  • 举报
回复
你应该先确定是不是proc的问题,如果真有这个问题,那你发现了一个DB2的bug啊,呵呵
Mr_Bean 2009-10-21
  • 打赏
  • 举报
回复
数据库一直都有类似问题 但是我碰到的只是存储奇数尾数才会出 现在能缓解方法是decimal转为double

SQL语法大全 SQL语法大全 1. ASP与Access数据库连接: 2. ASP与SQL数据库连接: 建立记录集对象: set rs=server.createobject("adodb.recordset") rs.open SQL语句,conn,3,2 3. SQL常用命令使用方法: (1) 数据记录筛选: sql="select * from 数据表 where 字段名=字段值 order by 字段名 [desc]" sql="select * from 数据表 where 字段名 like \'%字段值%\' order by 字段名 [desc]" sql="select top 10 * from 数据表 where 字段名 order by 字段名 [desc]" sql="select * from 数据表 where 字段名 in (\'值1\',\'值2\',\'值3\')" sql="select * from 数据表 where 字段名 between 值1 and 值2" (2) 更新数据记录: sql="update 数据表 set 字段名=字段值 where 条件表达式" sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式" (3) 删除数据记录: sql="delete from 数据表 where 条件表达式" sql="delete from 数据表" (将数据表所有记录删除) (4) 添加数据记录: sql="insert into 数据表 (字段1,字段2,字段3 …) values (值1,值2,值3 …)" sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表) (5) 数据记录统计函数: AVG(字段名) 得出一个表格栏平均值 COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计 MAX(字段名) 取得一个表格栏最大的值 MIN(字段名) 取得一个表格栏最小的值 SUM(字段名) 把数据栏的值相加 引用以上函数的方法: sql="select sum(字段名) as 别名 from 数据表 where 条件表达式" set rs=conn.excute(sql) 用 rs("别名") 获取统的计值,其它函数运用同上。 (5) 数据表的建立和删除: CREATE TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… ) 例:CREATE TABLE tab01(name varchar(50),datetime default now()) DROP TABLE 数据表名称 (永久性删除一个数据表) 4. 记录集对象的方法: rs.movenext 将记录指针从当前的位置向下移一行 rs.moveprevious 将记录指针从当前的位置向上移一行 rs.movefirst 将记录指针移到数据表第一行 rs.movelast 将记录指针移到数据表最后一行 rs.absoluteposition=N 将记录指针移到数据表第N行 rs.absolutepage=N 将记录指针移到第N页的第一行 rs.pagesize=N 设置每页为N条记录 rs.pagecount 根据 pagesize 的设置返回总页数 rs.recordcount 返回记录总数 rs.bof

5,889

社区成员

发帖
与我相关
我的任务
社区描述
IBM DB2 是美国IBM公司开发的一套关系型数据库管理系统,它主要的运行环境为UNIX(包括IBM自家的AIX)、Linux、IBM i(旧称OS/400)、z/OS,以及Windows服务器版本
社区管理员
  • DB2
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧