如何通过 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
,但它似乎没有达到我想要的效果。
我有两个用户/模式,我们称他们为 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
。这意味着此查询将仅返回与表属于同一用户的索引信息。
我能想到三种可能的解决方法:
-
始终在同一架构中创建索引和表(即让它们拥有相同的所有者)。不幸的是,这并不总是一种选择。
将
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.owner
为table_schema
,因此该值将设置为索引的模式,而不是表.
@Joachim Sauer:那我会选择选项 1) 或 3)以上是关于如何通过 JDBC 获取 Oracle 表中的所有索引,即使它们由不同的用户拥有?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Oracle 中的 JDBC 批量插入中获取生成的密钥?
如何获取新插入Oracle数据库Sequence值的5种方法
如何使用 jdbc 从 Oracle 中的结果集中获取模式名称?