【问题标题】:Delphi ADO - how to set default dataset column type without designerDelphi ADO - 如何在没有设计器的情况下设置默认数据集列类型
【发布时间】:2014-08-12 07:12:49
【问题描述】:

使用 Delphi 2007。

我们不使用设计器来配置我们的数据集。它是从 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 实际:BCD'。

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

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

【问题讨论】:

  • 当您确实使用设计师时,您如何解决问题?也看看这里:delphigroups.info/2/d1/218434.html 和这里:stackoverflow.com/a/23295331/937125
  • 我不确定使用设计时字段编辑是否真的有帮助,我不知道我们没有使用它。谢谢,这些链接很有趣。第一个链接是我喜欢的行为,但我不太喜欢更改 ADODB 的想法。
  • 您写道“有没有办法强制 ADO...而不使用设计器?” - 所以我假设您可以强制 ADO“使用设计器”更改字段类型。无法强制 ADO 更改字段类型 AFAIK。负责初始化它的方法是TCustomADODataSet.InternalInitFieldDefs
  • "但我不太喜欢更改 ADODB 的想法" 您不需要更改 Delphi 的 ADODB.pas。将其复制到您的项目目录并在那里修补它。
  • 谢谢。从更多阅读中,我认为您是正确的。是的,我了解补丁,但它并不是一个真正优雅的解决方案,并且可能会使后来的开发人员感到困惑。我宁愿在框架的范围内工作,除非真的推动自己改变它。我想我最终会为受影响的查询关闭 BCD。如果您愿意,请将您的注释添加到一个说明不可能的答案中,我会将其标记为正确答案。

标签: oracle delphi ado odac


【解决方案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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    相关资源
    最近更新 更多