从数据库系统表中选择所有索引,根据Oracle中的索引聚合数据
Posted
技术标签:
【中文标题】从数据库系统表中选择所有索引,根据Oracle中的索引聚合数据【英文标题】:Select all indexes from database system table, aggregate data based on the index in Oracle 【发布时间】:2021-09-11 09:03:32 【问题描述】:我正在使用 Oracle 作为 CRM 的数据库。
我被要求根据特定条件生成一个完整的索引列表,以便检查表名。
我找到并详细说明了以下查询:
select ind.index_name,
ind_col.column_name,
tab_cols.DATA_DEFAULT,
ind.table_name
from sys.all_indexes ind
inner join sys.all_ind_columns ind_col on
ind.owner = ind_col.index_owner and ind.index_name = ind_col.index_name
left outer join sys.all_TAB_COLS tab_cols on
ind_col.COLUMN_NAME = tab_cols.COLUMN_NAME and
INDEX_TYPE='FUNCTION-BASED NORMAL' and
tab_cols.OWNER = ind.owner and
ind_col.COLUMN_NAME like 'SYS_NC%' and
tab_cols.TABLE_NAME = ind.table_name
where [requested conditions]
order by ind.table_name,INDEX_NAME;
这个查询生成了大约 1.600 行,其中大部分是重复的 INDEX_NAME 值,因为如果索引有多个参数,我会重复该字段。
我想做的是:
-
将 ind_col.column_name 中定义的一个索引的所有值分组到一列中,逗号分隔
(如果可能)具有 tab_cols.DATA_DEFAULT (long) 的值,而不是 ind_col.column_name,以防第一个值不为空。
我可以请你帮忙吗?
非常感谢您的回复!
【问题讨论】:
查看LISTAGG
以获取逗号分隔列表和NVL
或NVL2
以处理NULL/NOT NULL 值
DATA_DEFAULT 不是 CLOB 而是 LONG 不幸的是,它非常非常难以保存转换为 VARCHAR2。我最终在我的 DBMS(Oracle 19c 企业版)上遇到了数据库故障“SP2-0642:SQL*Plus 内部错误状态 2147,上下文 0:0:0 无法安全继续”。
【参考方案1】:
sys.listagg can be used on the columns you want to aggregate:
'''
select substr(sys.listagg(ind.index_name||','),1,length(sys.listagg(ind.index_name||',')-1)) as index_name,
ind_col.column_name,
tab_cols.DATA_DEFAULT,
ind.table_name
from sys.all_indexes ind
inner join sys.all_ind_columns ind_col on
ind.owner = ind_col.index_owner and ind.index_name = ind_col.index_name
left outer join sys.DBA_TAB_COLS tab_cols on
ind_col.COLUMN_NAME = tab_cols.COLUMN_NAME
and INDEX_TYPE='FUNCTION-BASED NORMAL'
and tab_cols.OWNER = ind.owner and ind_col.COLUMN_NAME like 'SYS_NC%'
where [list of custom conditions]
group by
ind_col.column_name,`enter code here`
tab_cols.DATA_DEFAULT,
ind.table_name
order by INDEX_NAME;
`enter code here`
'''
【讨论】:
你真的试过了吗?你得到了什么结果? 不幸的是,这部分工作,因为我仍然使用 tab_cols.DATA_DEFAULT 得到 ORA-00997,因为它是一个长类型 如果可能,请排除 data_fault 列。如果没有,解决方法是使用:substr(to_char(tab_cols.DATA_DEFAULT),1,4000)。如果 data_default 的值较长,则仅使用前 4000 个字符。 . @little_amb 我已经尝试过了,我目前使用 excel 对数据进行分组......无论如何,我认为不可能排除该字段,如果我希望在查询中显示公式的数据 @little_amb 我已经尝试了建议的转换,但它返回了 Oracle 错误。【参考方案2】:这就是我得到的。我最终在我的 DBMS(Oracle 19c 企业版)上遇到了数据库故障“SP2-0642:SQL*Plus 内部错误状态 2147,上下文 0:0:0 无法安全继续”。尽管如此,也许它会有所帮助。
with
function get_data_default(
p_owner varchar2,
p_table_name varchar2,
p_column_name varchar2,
p_index_type varchar2) return varchar2
as
v_long long;
begin
select data_default
into v_long
from dba_tab_cols
where owner = p_owner
and table_name = p_table_name
and column_name = p_column_name
and p_index_type = 'FUNCTION-BASED NORMAL'
and column_name like 'SYS_NC%';
return substr(v_long, 1, 4000);
end get_data_default;
select
ind.owner,
ind.index_name,
listagg(
coalesce(
get_data_default(ind.table_owner, ind.table_name, ind_col.column_name, ind.index_type),
ind_col.column_name), ', ')
within group (order by ind_col.column_position) as cols,
ind.table_name
from dba_indexes ind
inner join dba_ind_columns ind_col on ind.owner = ind_col.index_owner
and ind.index_name = ind_col.index_name
where [list of custom conditions]
group by ind.owner, ind.index_name, ind.table_name
order by ind.owner, ind.index_name, ind.table_name;
(如果您想知道为什么 ind.table_name 出现在 GROUP BY
子句中,尽管它已按索引所有者和名称区域分组:Oracle 需要这样做,因为 DBMS 无法检测到 GROUP BY
中的功能依赖关系,还没有。)
【讨论】:
非常感谢!让我们希望有人能从这里开始工作:) 不幸的是,我对 Oracle、SQL 和 sys 表(以及 idex)还很陌生 否则,还有其他地方可以获取 SYS_NC 字段的值吗?以上是关于从数据库系统表中选择所有索引,根据Oracle中的索引聚合数据的主要内容,如果未能解决你的问题,请参考以下文章