decimal(20, 8)在dataset中只能以TFloatField(EnableBCD=false)或TBCDField显示:
1,如果使用TBCDField,则只能显示和输入4位小数;2,如果使用TFloatField,则只能有15位有效数字,达不到精度要求如何使用TFMTBCDField,或其它方式能达到显示和输入20位精度,8位小数位?

解决方案 »

  1.   

    就是通过ado连接sql server
    DataSet中产生的字段类型只能是TFloatField或TBCDField
    达不到decimal(20, 8)的精度和小数要求
      

  2.   

    我真服了你了,在Delphi里难道只有这些字段存储数字吗?你难道不可以使用字符串?
    32位小数的都做过。
      

  3.   

    楼上的别着急我这是3层的结构,DataSet字段也不是手动添加,况且整个系统中所有字段都手动添加也不现实能不能介绍一下您的做法?多谢!
      

  4.   

    再声明一下:数据库中只能用decimal,不能用varchar,因为数据库有很高的速度要求,每秒并发数很大,需要计算,varchar和decimal的区别很大。
      

  5.   

    另外在delphi的adoquery中手动添加一个字段,指定类型String
    打开query时会有错误:
    Type mismatch for field '' excepting: String actual: BCD.请Hank(星星农场)介绍一下您的做法,非常感谢!
      

  6.   

    在那里计算?如果能直接计算,那可以在Delphi中设置字段类型为TCurrencyField即可
    不想显示符号可以
    Currency:=False;
    但是注意
    DisplayWidth:=20
    就是你的字段长度,剩下的不用我说了吧至于手动添加问题,这个很简单啊,不可能你所有的表都有这种字段吧,可以通过动态添加字段的方式,就这几个字段调整默认的TBCDField为TCurrencyField即可
      

  7.   

    我想楼上的并未理解我的问题。我的问题是:
    数据库中decimal(20, 8)的数据类型在客户端如何输入,不考虑把数据库的decimal改为其他类型。就是怎么能输入12位整数8位小数的数字。
    TCurrencyField本质上即是TFloatField,唯一区别是他的字段类型为ftCurrency。TFloatField的精度是15位,decimal(20,8)的精度是20位,比如在客户端输入123456789012.12345678这个数值,这个数值对decimal(20,8)是合法的,可以直接在数据库中输入。但是TFloatField和TCurrencyField的精度是15位,在保存时会忽略后面超出的位,只把123456789012.123保存到数据库。TCurrencyField和TFloatField我做过测试。如果手动添加字段,把类型定义为String会有Type mismatch for field '' excepting: String actual: BCD.错误。如果手动添加字段,把类型定义为Variant,则可以实现,但只限于在adoquery中添加,3层结构中在adoquery中添加一个variant类型字段,再在TClientDataSet中打开DataSet或加入字段时会提示adoquery中variant类型的字段类型未定义。
      

  8.   

    Hank(星星农场) ,兄台还是试验一下为好。
    货币类型小数仅仅保存四位,
    浮点的精度确实是15位,按照楼主的要求,我测试过,不能保存它要求的精度
    楼主如果要使用字符,就必须使数据库类型和程序中的类型一致。
    还有可恨的decimal类型,在数据库中确定可以保存小数点八位以后。但是在delphi中仅仅保存四位。设置了属性也不可以。原来看了楼主的帖子,还没有找到完美的解决方案!
      

  9.   

    呵呵,看来这个问题的难度是不小,综合看来,有多种解决方案,当然问题主要出在Borland身上
    1、修改ADODB.pas的源代码,也就是修改从Recordset转换成DataSet的字段定义部分,这个问题很多人讨论过,强行修改decimal的对应关系
    2、修改DB.pas的源代码,也就是如果ADO调用的时候直接从Recordset中取数据
    3、建立一个新的自定义字段类,譬如TDoubleField,然后自行定义,当然这个时候也得修改ADODB.pas及DB.pas的源代码以上三种方法是一劳永逸的方法,最好是第3种方法第4种方法,这种情况适用于此类字段比较少的情况,就是修改字段的GetText和SetText方法,譬如procedure TForm1.ADOQuery1DecFieldSetText(Sender: TField; const Text: String);
    begin
      ADOQuery1.Recordset.AbsolutePosition:=ADOQuery1.RecNo;
      ADOQuery1.Recordset.Fields[1].Value:=Text;
    end;procedure TForm1.ADOQuery1DecFieldGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    begin
      ADOQuery1.Recordset.AbsolutePosition:=ADOQuery1.RecNo;
      Text:=VarToStr(ADOQuery1.Recordset.Fields[1].Value);
    end;当然,由于Borland的先天不足,实际代码可能还要多一些,要加入很多判断,其实基本原理和前面的方法差不多,就是绕开Borland的字段定义,直接向Recordset中写数据5、这种方法一般太罗索,就是直接绕开数据感应控件去操作,这样可以随心所欲了。综合看来,第3种方法最好
      

  10.   

    似乎delphi根本没有哪个浮点数据类型能表示123456789012.12345678
    这个数值(除了Variant,Variant在3层系统中不方便使用)。
    Double,Extend都不行.net中有decimal类型,可以表示29位数字。
    delphi2006 for win32仍未支持decimal类型。所以,上面的几种方法都不太可行,
    方法4,5或许可行,但是改动太大。
    暂时不做修改了,只支持15位精度。
      

  11.   

    如果想改动小,第4种方法最简单,把这两个写为通用过程,然后有字段的地方调用即可。然后打开表的时候动态设置字段的OnGetText和OnSetText事件为通用过程即可,这个相对简单很多,窗口不用任何改动。其实数据库在Delphi后台所有的数据均为文本传递,当OnSetText的时候才转换,所以最早说的通过string控制decimal数据既是如此,其实Delphi本身就是通过string控制decimal数据,这个可以去看DB.pas的源代码。
      

  12.   

    方法4对adoquery确实可以但是在3层结构中:
    ClientDataSet-->DataSetProvider-->AdoQuery-->DataBase
    这种情况就无能为力了