Delphi ADO - 如何在没有设计器的情况下设置默认数据集列类型

时间:2014-08-12 07:12:49

标签: oracle delphi ado odac

使用Delphi 2007.

我们不使用设计器来配置我们的DataSet。它是从SQL查询自动构建的。因此,我们需要一个在运行时构建字段的解决方案。

我需要使用ADO从Oracle的NUMBER(19,0)列中选择一个大数字(例如2305843009213693951)。我们的查询在SQLServer中工作,其中列定义为BIGINT并自动映射到TLargeintField但对于Oracle,它映射到TBCDField。此行为记录在几个地方,例如here - TADOQuery.EnableBCD

问题(如同一页中所述)是我们的数字在某些情况下太大而且抛出了溢出异常(它在引擎盖下使用了小数)。正如预期/记录 - 如果我使用TADOQuery.EnableBCD(false),那么该列将映射到TLargeintField,这是我想要的。但是这个选项是为所有列设置的,看起来有点沉重。

描述了另一种选择:

  

注意:对于数字超过19位有效数字的字段,您可以使用TVariantField类型的持久字段对象。 TFloatField和TBCDField类对于这种大小的字段缺乏足够的容量。 TVariantField允许将字段数据获取和设置为字符串,防止由于容量不足而导致数据丢失。但是,无法对通过TVariantField对象访问的数字执行算术运算。

所以我尝试按this article - Creating a ClientDataSet's Structure at Runtime using TFields中的说明手动配置字段到列。但这似乎不起作用,因为我得到了例外:“字段'total_rec'的类型不匹配期望:LargeInt actual:BCD'。

那么有没有办法强制ADO在不使用设计器的情况下为NUMBER(19,0)返回TLargeintField类型字段的数据集?

有趣的是,ODAC将列映射到TLargeintField,但我们应该支持ODAC和ADO。

1 个答案:

答案 0 :(得分:1)

我不相信有一种方法可以手动控制ADOQuery返回的列数据类型。我测试了覆盖kobik提到的程序,它确定了数据类型并且运行良好。但是我们不会使用这个解决方案,因为我查看了XE4中的相同代码,看起来它已被修改以用于大型BCD编号。我们可以等到2007年升级(希望明年)。

我添加到我的重写版本的InternalInitFieldDefs的代码是:

    if (F.Type_ = adNumeric) and (F.NumericScale = 0) and (F.Precision < 10) then
    begin
      FieldType := TFieldType(ftInteger);
    end

我添加了

    else if (F.Type_ = adNumeric) and (F.NumericScale = 0) and (F.Precision >= 19) then
    begin
      FieldType := ftLargeint;
    end;