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

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

我有两个用户/模式,我们称他们为 A 和 B。

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

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

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

  • 第一个参数 catalog 似乎完全被 Oracle JDBC 驱动程序忽略了。
  • 第二个参数schema 限制返回哪些表统计信息 和 索引的所有者
  • unique 和 approximate (大致)做了他们应该做的事情(除了给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。这意味着此查询将仅返回与表属于同一用户的索引信息。

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

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

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

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

所以基本上我的问题是:

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

【问题讨论】:

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

标签: oracle jdbc oracle11g database-indexes


【解决方案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.owner为table_schema,因此该值将设置为索引的模式,而不是表.
    • @Joachim Sauer:那我会选择选项 1) 或 3)
    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2014-01-26
    • 2011-09-23
    • 2012-08-06
    • 1970-01-01
    相关资源
    最近更新 更多