首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从ActiveRecord访问隐藏列(在Informix中)

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

Stack Overflow用户
提问于 2010-01-24 12:18:33
回答 1查看 987关注 0票数 1

许多数据库都有一个隐藏的主键列。MySQL将其实现为_rowid。在MySQL中,它实际上是指向先前定义的主键列的指针。但是,在其他数据库(在我的例子中是Informix)中,该列独立于故意定义的主键。我正在编码的数据库主要是在依赖于Informix隐藏列ROWID而不是定义主键的实践下设计的。我使用Informix JDBC驱动程序从JRuby on Rails连接到Informix。一切都很好,只是我想不出一种方法让隐藏的rowid列显示为ActiveRecord属性。所有其他字段都在那里,但不是rowid。如果我使用Whatever.find_by_sql("SELECT rowid,* FROM whatevertable")查询一个模型,它会返回一个包含“任何”对象的数组,但其中没有rowid列。

我已经研究过调整JDBC驱动程序、ActiveRecord或数据库,但都没有结果。

任何指导都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-01-25 11:55:42

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

其次,为什么不直接对表使用声明的主键,而不是在幕后钻研-尤其是在幕后钻研版本不起作用的情况下。

我不清楚为什么您正在使用的显式表示法没有按照您的要求进行操作;这可能是JDBC驱动程序在它的鼻子不属于它的地方戳它的鼻子。您在结果集中返回了多少列?如果它不是您选择的数字(表中的列数加1),那么就有问题了。

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

代码语言:javascript
复制
SQLIDEBUG=2:sqli

这将在运行C API的进程(ESQL/C、ODBC等)的当前目录中创建一个以'sqli_‘开头的文件。我假设JDBC驱动程序也应该使用相同的机制。

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

假设您捕获了SQLI (SQL Interface)输出,然后可以使用'sqliprint‘打印它。您将查找发送到IDS的SQL。如果它不包含ROWID,那么您可以相当确定JDBC驱动程序正在与您玩愚蠢的游戏。然而,还不清楚你会做些什么来解决这个问题。也许可以尝试一个表别名(例如't'),然后:

代码语言:javascript
复制
SELECT t.ROWID, t.* FROM WhateverTable t WHERE ...

如果结果是JDBC调整了ROWID,我们也可以尝试别名:

代码语言:javascript
复制
SELECT ROWID AS pk_column, t.* FROM WhateverTable AS t WHERE ...

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

如果你发现了什么有趣或有用的东西,请随时与我们联系。

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

好的;这是一个设计决策,如果您的任何客户有足够大的数据量,碎片可能是有益的,那么应该在您的下一次主要升级时对其进行审查。请记住,碎片表没有虚拟ROWID列;您可以使用create TABLE或ALTER statements语句中的with ROWIDS子句,使用物理ROWID列创建它们。

使用log4jdbc我能够确认发送到

的查询确实包含对rowid的请求。返回该值,并且JDBC驱动程序强制转换ResultSet中的每一列;我可以看到它正在强制转换rowid列(ResultSet.getLong())。但是,返回的ActiveRecord对象不包括rowid值。我相信这是因为当要求JDBC驱动程序提供用于建立ActiveRecord类的可用属性的表的模式时,不会返回行I。感谢您提供的任何意见。

在获取信息方面做得很好。不经意间,我对JDBC驱动程序可能正在做的事情的了解开始耗尽-这可能是IBM/Informix技术支持的一些东西。我的脑海中出现了各种各样的问题--我甚至不确定问题出在JDBC驱动程序、整个JDBC设计中,还是在JDBC之上;我的想象力无论如何都不是该领域的专家。(我可以拼写Java -C,对吗?)

您是否尝试过将ROWID篡改到语句的最后一列?

代码语言:javascript
复制
SELECT *, ROWID FROM WhereEver

把它弄成别名怎么样?

代码语言:javascript
复制
SELECT *, ROWID AS T_RowID FROM WhereEver

如果JDBC驱动程序同时看透了这两个问题,那么它就太努力了,给每个人都带来了伤害。事实上,我甚至不确定我是否知道它是如何处理视图的。

我有一个元素表:

代码语言:javascript
复制
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的视图,然后对其进行查询:

代码语言:javascript
复制
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程序,但它“应该”工作(但由于原始查询也“应该”工作,我不确定我会在多大程度上依赖“应该工作”断言)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2125926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档