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

发布于 2024-12-01 10:49:18 字数 2758 浏览 1 评论 0原文

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

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

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

我想要的信息是:模式 A 中的表 TAB 上有哪些索引(又名所有者 A< /代码>)。我不关心索引的所有者,只关心它们位于该特定表上。

通过使用 getIndexInfo 进行实验,我发现了以下内容:

  • 第一个参数 catalog 似乎完全被 Oracle JDBC 驱动程序忽略。
  • 第二个参数schema限制返回哪个表统计信息索引的所有者
  • 唯一 和 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

正如您所看到的两者 < code>table_name i.owner 仅限于TAB。这意味着此查询将返回与表属于同一用户的索引信息。

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

  1. 始终在同一模式中创建索引和表(即让它们具有相同的所有者)。不幸的是,这并不总是一个选择。
  2. schema 设置为 null 的查询。一旦两个模式包含相同的表名,这就会变得很难看(因为无法找出给定模式是在哪个表(即哪个表所有者)上)。
  3. 直接执行该 SQL(使用executeQuery())。我宁愿不跌到这个地步,除非这是绝对不可避免的。

这些解决方法看起来都不是特别令我满意,但如果没有其他办法,我可能不得不回退到直接 SQL 执行。

数据库和 JDBC 驱动程序均为 11.2.0.2.0。

所以基本上我的问题是:

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

Yes, I know about DatabaseMetadata.getIndexInfo, but it doesn't seem to do what I want.

I've got two users/schemas, let's call them A and B.

There's a table in A called TAB. The user B created an index on A.TAB, let's call that index IND.

The information that I want is: what indices are there on the table TAB in the schema A (a.k.a with the owner A). I don't care about the owner of the indices, just that they are on that specific table.

Experimenting with getIndexInfo I found out the following things:

  • the first argument catalog seems to be entirely ignored by the Oracle JDBC driver.
  • the second argument schema restricts which table statistics is returned and the owner of the index
  • unique and approximate do (roughly) what they should (except that giving approximate=false will actually execute an update statistics statement).

Having traced the SQL the JDBC driver executes on getIndexInfo(null, "A", "TAB", false, true), I got this:

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

As you can see both table_name and i.owner are restricted to being TAB. This means that this query will only return index information that is owned by the same user as the table.

I can think of three possible workarounds:

  1. always create the index and the table in the same schema (i.e. let them have the same owner). Unfortunately that's not always an option.
  2. Query with schema set to null. This would get ugly as soon as two schemata contained the same table name (because there's no way to find out on which table (i.e. which table owner) a given schema is).
  3. execute that SQL directly (using executeQuery()). I'd rather not fall down to this level, unless it's absolutely unavoidable.

None of those workarounds look particularly pleasing to me, but if nothing else works, I might have to fall back to direct SQL execution.

Both the Database and the JDBC Driver are at 11.2.0.2.0.

So basically my questions are:

  1. Is this a bug in the JDBC driver, or is there some logic behind it that I'm unaware of?
  2. Is there a simple and reasonably portable way to get Oracle to give me the information that I need?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

极度宠爱 2024-12-08 10:49:18

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

select * from dba_indexes

使用该视图,获取您需要的信息几乎是微不足道的。

然而,访问 dba_ 表和视图需要用户具有特殊权限,但由于您不想向每个人授予 DBA 权限,因此您可以:

grant select any dictionary to username

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

万一您想探索 Oracle 词典,请尝试:

select * from dict

此致。

I suggest you query directly the Oracle dictionary tables, BUT start with:

select * from dba_indexes

Using that view it should be almost trivial to get the info you need.

However, accesing the dba_ tables and views requires the user to have special privileges, but since you don't want to give DBA privilege to everyone, you can just:

grant select any dictionary to username

connected as system or sys so the selected user can query the dictionary.

Just in case you want to explore Oracle's dictionary, try:

select * from dict

Best regards.

狂之美人 2024-12-08 10:49:18

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

这将是我首选的做法。

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

当然你可以找到它,因为返回的结果集getIndexInfo() 确实包含每个表的正确架构。但您无法找出索引属于哪个模式。

直接执行该SQL

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

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

always create the index and the table in the same schema (i.e. let them have the same owner). Unfortunately that's not always an option.

That would be my preferred way of doing it.

Query with schema set to null. This would get ugly as soon as two schemata contained the same table name (because there's no way to find out on which table (i.e. which table owner) a given schema is)

Of course you can find that out, because the result set returned by getIndexInfo() does contain the correct schema for each table. But you can't find out in which schema the index is.

execute that SQL directly

I would actually use a modified version of that query that also returns the schema for each index to alleviate the identification of the index.

But again: I would also create the index and the table in the same schema.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文