1

我正在一个只读的 oracle 数据库(通过 oracle_enhanced_adapter 连接)上使用 Ruby on Rails 3.0。

遇到已知的“n+1 查询”问题,我尝试了包含方法。
与 Rails 指南中的描述不同,生成的第二个查询列出了所需的 id 不是整数,而是浮点值的字符串表示形式。原始 ID 的类型为 NUMBER。

不幸的是,数据库 NLS 设置是针对德国的,包括NLS_NUMERIC_CHARACTERS需要“,”作为小数分隔符的。所以我总是得到一个ORA-01722错误,如此处所述

更确切地说:

@var.assoc.includes(:another_assoc).where("column_1 = ?", some_value)

产量

ActiveRecord::StatementInvalid: OCIError: ORA-01722: invalid number: SELECT "TABLE_A".* FROM "TABLE_A" WHERE ("TABLE_A"."ID" IN ('1715.0','1716.0','1717.0','1718.0' ,'1719.0','1720.0','1721.0'))

(我不得不简化上面的 Rail 代码,因为它包含一些令人分心的细节,比如“字符串到符号”的转换)

如前所述,数据库是只读的,所以使用

alter session set nls_numeric_characters = '.,'

直接在数据库上工作。但我无法找到改变 rails 会话的正确方法。

我发现的所有内容似乎都引用了 Rails 2 或使用了已弃用的函数。
我怎样才能为 Rails 3.0 解决这个问题?

或者:如何强制 Rails(或者 oracle_enhanced_adapter)将所有列出的 id 转换为 Fixnum?

谢谢和最好的问候,蒂姆

4

2 回答 2

1

我们在使用 Oracle 时遇到了同样的问题,我们通过将以下代码放入初始化程序(将其放入config/initializers/something.rb)来解决它:

BigDecimal.class_eval do
  alias :old_to_s :to_s

  def to_s(format='F')
    old_result = self.old_to_s(format)
    (old_result[-2..-1] == ".0" ? old_result[0..-3] : old_result)
  end
end

它是由您用作主键的列类型引起的。如果您将其声明为 a NUMBER,它将被转换为 a BigDecimal。或者,您可以将您的 id 声明为NUMBER(10)或类似的东西,这将更明显地映射到 a FixNum(其 id 将被正确转换)。

希望这可以帮助。

于 2010-11-22T13:17:46.253 回答
1

如果有人来寻找ORA-01722使用activerecord-oracle_enhanced-adaptergem 提出的问题,这里有一个更新的答案。

ActiveRecord::StatementInvalid (OCIError: ORA-01722: invalid number)

保存 BigDecimal 时,在最近的版本(Rails 6 和 oracle gem 6.0)中仍然会发生这种情况

看到这个非常好的答案database.yml来使用配置修复小数分隔符

development:
  adapter: oracle_enhanced
  username: XXX
  password: XXX
  host: XXXX
  nls_numeric_characters: '.,'
于 2020-09-16T13:35:08.040 回答