我的Oracle 10gR2数据库包含IOT表:
create table countries (
id number primary key,
name varchar2(30) not null enable
) organization index;
我尝试使用此Java(版本1.6)代码更新表值:
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ResultSet src = stmt.executeQuery("select id, name from countries");
src.next();
src.updateString("name", "__test__");
src.updateRow();
但是updateRow抛出SQLException(ORA-01410:无效的ROWID)。如果我尝试更新堆(普通)表 - 一切正常。
我已将此代码用于不同版本的oracle驱动程序(来自此处http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_10201.html)
经过一些研究后,我发现IOT和HEAP表有不同的rowid格式:
物联网示例 BAJzKgwCwRb +
HEAP示例AAAbgVAAJAAMyrAAAA
但我仍然不知道如何解决这个问题。你有什么想法吗?
答案 0 :(得分:1)
您是否可以获得查询的扩展SQL跟踪的结果,以了解JDBC在幕后的操作?我怀疑它正在尝试
UPDATE COUNTRIES SET NAME = '__TEST__' WHERE ROWID = :rowid_fetched
和ROWID在Oracle IOT中意味着完全不同的东西;它不是行的不可变地址,而是对行的路径的猜测。
我对如何执行此操作的建议是将系统生成的时间戳字段传播到所有表上,并将其用于并发控制,而不是声明可更新的记录集 - 这将记录每个记录的锁定记录集。
然后您的应用程序将正常获取行集,但会发出如下语句:
UPDATE COUNTRIES SET NAME = '__TEST__' WHERE MOD_TS = :mod_ts_fetched
给予无国籍乐观锁定。
答案 1 :(得分:1)
看起来你的桌子不一定需要IOT。我建议你将它重新创建为普通表,并在ID和名称上添加索引。相同的性能,相同的逻辑,没有ROWID问题。