如何从ActiveRecord访问隐藏列(在Informix中)

时间:2010-01-24 04:18:33

标签: ruby-on-rails activerecord informix

许多数据库都有隐藏的主键列。 MySQL将其实现为_rowid。在MySQL的情况下,它实际上是指向先前定义的主键列的指针。但是在其他数据库(在我的情况下,Informix)中,此列独立于故意定义的主键。我编写的数据库主要是根据Informix隐藏列ROWID而不是定义主键的做法设计的。我使用Informix JDBC驱动程序从JRuby on Rails连接到Informix。一切都很好,除了我无法弄清楚如何使隐藏的rowid列显示为ActiveRecord属性。所有其他领域都在那里,只是没有rowid。如果我使用Whatever.find_by_sql(“SELECT rowid,* FROM whatevertable”)查询模型,它将返回一个“Whatever”对象的数组,但rowid列不存在。

我调查过调整JDBC驱动程序,ActiveRecord或数据库;没有结果。

任何指导都将不胜感激。

1 个答案:

答案 0 :(得分:0)

首先,请注意,如果您的表是碎片的,它将没有ROWID - 除非您使用WITH ROWIDS子句创建它,在这种情况下,ROWID将成为索引的物理列而不是虚拟列。

其次,为什么不直接使用声明的主键表而不是在幕后钻研 - 特别是当幕后版本的钻孔不起作用时。

我不清楚为什么你使用的显式符号没有按照你的要求进行;这可能是JDBC驱动程序在其鼻子不属于的地方戳鼻子。您在结果集中返回了多少列?如果它不是您选择的数字(表格中的列数加1),那么某些东西非常可疑。

如果我需要查看JDBC驱动程序发送给服务器的内容,我将启用SQLI调试跟踪 - 在客户端,或者如果客户端不合作,则在服务器端启用。在普通(基于C)的API中,启用SQLI调试是设置环境变量的问题:

SQLIDEBUG=2:sqli

这将在运行C API(ESQL / C,ODBC等)的进程的当前目录中创建名称以“sqli_”开头的文件。我假设相同的机制应该与JDBC驱动程序一起使用。

如果SQLIDEBUG不能与JDBC一起使用,那么你的工作就更难了 - 你需要在服务器端启用SQLI调试。

假设您捕获了SQLI(SQL接口)输出,则可以使用“sqliprint”进行打印。您将查找发送到IDS的SQL。如果它不包含ROWID,那么您可以相当确定JDBC驱动程序正在与您玩愚蠢的游戏。但是,目前尚不清楚你要做些什么来解决这个问题。也许尝试表别名(例如't')和:

SELECT t.ROWID, t.* FROM WhateverTable t WHERE ...

如果事实证明JDBC正在调整ROWID,我们也可以尝试这样做:

SELECT ROWID AS pk_column, t.* FROM WhateverTable AS t WHERE ...

(AS在表名后是可选的。)

如果您发现任何有趣或有用的内容,请随时发布。


  

数据库已安装在多个位置,并且已编译的应用程序(源代码不可用)在数据库架构发生更改时会中断,因此我无法添加合法的主键。这些应用程序依赖于rowid作为主键。

行;这是一个设计决策,应在下次主要升级时进行审核如果您的任何客户拥有足够大的数据量,那么碎片化可能会有所帮助。请记住,碎片表没有虚拟的ROWID列;您可以使用CREATE TABLE或ALTER FRAGMENT语句中的WITH ROWIDS子句使用物理ROWID列创建它们。

  

使用log4jdbc我能够确认发送到Informix的查询是否包含对rowid的请求。返回值,JDBC驱动程序转换ResultSet中的每一列;我可以看到它正在转换rowid列(ResultSet.getLong())。但是,返回的ActiveRecord对象不包含rowid值。我相信这是因为当JDBC驱动程序被要求提供表的模式(用于建立ActiveRecord类的可用属性)时,不会返回rowid。任何意见都表示赞赏......

获取信息做得很好。另外,我对JDBC驱动程序可能正在做什么的了解开始耗尽 - 这可能是IBM / Informix技术支持部门要采取的措施。我脑子里出现了各种各样的问题 - 我甚至不确定问题是在JDBC驱动程序,整个JDBC设计中,还是在JDBC之上;我不是想象中的任何一位专家。 (我可以拼写Java - C;是吗?)

您是否尝试将ROWID摆弄到声明的最后一列?

SELECT *, ROWID FROM WhereEver

与此相关的是什么?

SELECT *, ROWID AS T_RowID FROM WhereEver

如果JDBC驱动程序看到了这两者,那么它的工作太过艰难,并且每个人都会受到伤害。实际上,我甚至不确定我是否知道它如何与视图一起使用。

我有一张元素表:

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL UNIQUE CONSTRAINT c1_elements
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
    name            CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
    atomic_weight   DECIMAL(8,4) NOT NULL,
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

INSERT INTO elements VALUES(  1, 'H',   'Hydrogen',        1.0079, 'Y');

我能够在该表上创建一个包含ROWID的视图,然后查询它:

CREATE VIEW x_elements(atomic_number, symbol, name, x_rowid)
    AS SELECT atomic_number, symbol, name, ROWID AS x_rowid
         FROM elements;

SELECT * FROM x_elements WHERE x_rowid <  512;
SELECT * FROM x_elements WHERE x_rowid >= 512;

这两个查询产生了不相交的数据集。您可能能够利用您的系统来利用它。如有必要,您可以重命名基表(例如'WhateverTable'变为'Base_Whatever')然后创建视图'WhateverTable'以从Base_Whatever中选择数据以及ROWID。我还没有正式尝试使用JDBC程序,但它应该可以工作(但由于原始查询也“应该”起作用,我不确定我对'应该工作'主张的依赖程度如何)。