【发布时间】: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。如果您愿意,请将您的注释添加到一个说明不可能的答案中,我会将其标记为正确答案。