如何通过 JDBC 获取 Oracle 表中的所有索引,即使它们由不同的用户拥有?

Posted

技术标签:

【中文标题】如何通过 JDBC 获取 Oracle 表中的所有索引,即使它们由不同的用户拥有?【英文标题】:How do I get all indices on a Table in Oracle via JDBC, even if they are owned by different users? 【发布时间】:2011-08-23 09:04:58 【问题描述】:

是的,我知道关于 DatabaseMetadata.getIndexInfo,但它似乎没有达到我想要的效果。

我有两个用户/模式,我们称他们为 AB

A 中有一个名为TAB 的表。用户BA.TAB 上创建了一个索引,我们称该索引为IND

想要的信息是:TAB 架构 A(也就是所有者 A)中有哪些索引。我不关心索引的所有者,只关心它们在那个特定的表上。

getIndexInfo做实验发现了以下几点:

第一个参数 catalog 似乎完全被 Oracle JDBC 驱动程序忽略了。 第二个参数schema 限制返回哪些表统计信息 索引的所有者 uniqueapproximate (大致)做了他们应该做的事情(除了给approximate=false 将实际执行更新统计语句)。

跟踪 JDBC 驱动程序在 getIndexInfo(null, "A", "TAB", false, true) 上执行的 SQL,我得到了这个:

select null as table_cat,
       owner as table_schem,
       table_name,
       0 as NON_UNIQUE,
       null as index_qualifier,
       null as index_name, 0 as type,
       0 as ordinal_position, null as column_name,
       null as asc_or_desc,
       num_rows as cardinality,
       blocks as pages,
       null as filter_condition
from all_tables
where table_name = 'TAB'
  and owner = 'A'
union
select null as table_cat,
       i.owner as table_schem,
       i.table_name,
       decode (i.uniqueness, 'UNIQUE', 0, 1),
       null as index_qualifier,
       i.index_name,
       1 as type,
       c.column_position as ordinal_position,
       c.column_name,
       null as asc_or_desc,
       i.distinct_keys as cardinality,
       i.leaf_blocks as pages,
       null as filter_condition
from all_indexes i, all_ind_columns c
where i.table_name = 'TAB'
  and i.owner = 'A'
  and i.index_name = c.index_name
  and i.table_owner = c.table_owner
  and i.table_name = c.table_name
  and i.owner = c.index_owner
order by non_unique, type, index_name, ordinal_position

如您所见both table_name i.owner 被限制为TAB。这意味着此查询将返回与表属于同一用户的索引信息。

我能想到三种可能的解决方法:

    始终在同一架构中创建索引和表(即让它们拥有相同的所有者)。不幸的是,这并不总是一种选择。 将schema 设置为null 进行查询。一旦两个模式包含相同的表名,这就会变得很难看(因为没有办法找出 哪个 表(即哪个表所有者)给定的模式是)。 直接执行该 SQL(使用executeQuery())。除非万不得已,否则我宁愿不要跌落到这种地步。

这些变通方法对我来说都不是特别满意,但如果没有其他方法可行,我可能不得不退回到直接执行 SQL。

数据库和 JDBC 驱动程序都位于 11.2.0.2.0。

所以基本上我的问题是:

    这是 JDBC 驱动程序中的错误,还是背后有一些我不知道的逻辑? 是否有一种简单且可移植的方式让 Oracle 向我提供我需要的信息?

【问题讨论】:

让 Oracle 为您提供所需内容的简单且可移植的方法是 SQL。第三方工具似乎具有您无法解决的限制。使用您从跟踪中确定的 SQL,并将第二行“and i.owner = 'A'”更改为“='B'” @Karl:是的,它可能会归结为这一点,但我不喜欢它,因为我可以使用getIndexInfo 处理几乎所有其他数据库。只要 Oracle 愿意,SQL 的硬编码可能 就会中断(我实际上不知道必要的结构有多稳定,因为幸运的是我以前不必降到这个级别)。 @Karl:顺便说一句:它不是第三方工具。它是 Oracle 自身 为该数据库提供的 JDBC 驱动程序。 看起来像一个错误。我建议将此问题报告给 Oracle 支持。 @Joachim Sauer。好消息是 Oracle 数据字典相当稳定。不是完全稳定的,而是小的增量变化,这些变化往往有很好的记录。是的,甲骨文和所有供应商一样,对事物的使用方式做出假设。值得庆幸的是,基本界面可靠且可用。 【参考方案1】:

我建议您直接查询 Oracle 字典表,但以:

select * from dba_indexes

使用该视图几乎可以轻松获得所需的信息。

但是,访问 dba_ 表和视图需要用户具有特殊权限,但由于您不想将 DBA 权限授予所有人,您可以:

grant select any dictionary to username

连接为 system 或 sys,以便所选用户可以查询字典。

以防万一您想探索 Oracle 的字典,请尝试:

select * from dict

最好的问候。

【讨论】:

【参考方案2】:

始终在同一架构中创建索引和表(即让它们拥有相同的所有者)。不幸的是,这并不总是一种选择。

这将是我的首选方式。

模式设置为空的查询。一旦两个模式包含相同的表名,这将变得很难看(因为无法找出给定模式在哪个表(即哪个表所有者)上)

当然你可以找到,因为 getIndexInfo() 返回的结果集确实包含每个表的正确模式。但是您无法找出 index 在哪个模式中。

直接执行那个 SQL

我实际上会使用该查询的修改版本,它还返回每个索引的架构以减轻索引的识别。

但同样:我也会在同一架构中创建索引和表。

【讨论】:

关于使用模式设置为null:不幸的是,在索引信息部分它返回i.ownertable_schema,因此该值将设置为索引的模式,而不是表. @Joachim Sauer:那我会选择选项 1) 或 3)

以上是关于如何通过 JDBC 获取 Oracle 表中的所有索引,即使它们由不同的用户拥有?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Oracle 中的 JDBC 批量插入中获取生成的密钥?

如何获取新插入Oracle数据库Sequence值的5种方法

逐页读取Oracle表中的所有数据

如何使用 jdbc 从 Oracle 中的结果集中获取模式名称?

使用 JDBC 连接位于同一服务器上不同数据库中的 2 个 Oracle 表中的数据

用oracle如何查询出一个表中的一个字段内容包含另一个表中的某个字段的值呢