无法通过 XML 查询多个表:XML 处理时出错
Unable to query multiple tables via XML: Error occurred in XML processing
我想为来自 all_tab_columns
的列表获取 column_name
和 table_name
(直到这里这不是问题)以及我想去的每个给定列到原始 table/column 并查看出现次数最多的最高值是什么。
通过下面的查询,我得到了 1 table:
中 1 个列示例的所需值
select col1
from (SELECT col1, rank () over (order by count(*) desc) as rnk
from T1
Group by col1
)
where rnk = 1
现在我想要这样的东西:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1;'))
returning content) as C
from all_tab_columns
where owner = 'S1'
and table_name in ('T1', 'T2', 'T3', 'T4')
;
但它不起作用。这是我得到的错误:
ORA-19202: Error occurred in XML processing
ORA-00933: SQL command not properly ended
ORA-06512: at "SYS.DBMS_XMLGEN", line 176
ORA-06512: at line 1
19202. 00000 - "Error occurred in XML processing%s"
*Cause: An error occurred when processing the XML function
*Action: Check the given error message and fix the appropriate problem
我举个例子。例如,这是我的两个 table; T1:
col.1 col.2 col.3
----- ---------- -----
y m1
y 22 m2
n 45 m2
y 10 m5
和 T2:
col.1 col.2 col.3
----- ------- -----
1 germany xxx
2 england xxx
3 germany uzt
3 germany vvx
8 US XXX
所以
- 来自 T1/Col.1 我应该得到 'y'
- 来自 T1/col.3 我应该得到 'm2'
- 来自 T2/col.3 我应该得到 'xxx'
等等。
报告给您的重要错误是:
ORA-00933: SQL command not properly ended
从 dbms_xmlgen.getxml()
调用中的查询中删除分号:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
-------^ no semicolon here
returning content) as C
from all_tab_columns
...
你的 XPath 似乎也是错误的;您正在寻找 /ROWSET/ROW/C
,但 C
是整个表达式的列别名,而不是正在计算的列。您需要在 查询中为列名 添加别名,并在 XPath 中使用它:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
-- ^^^
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
-- ^^^^^^
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content) as C
from all_tab_columns
...
您的样本数据得到:
TABLE_NAME COLUMN_NAME C
------------------------------ ------------------------------ ----------
T1 col.1 y
T1 col.2 224510
T1 col.3 m2
T2 col.1 3
T2 col.2 germany
T2 col.3 xxx
XML查询是 return 一个 XML 类型的结果,您的客户端显然显示为 (XMLTYPE)
。你可能会改变这种行为 - 例如在 Sql 开发人员中,从工具->首选项->数据库->高级->DIsplay XMl 网格中的值。但是您也可以将结果转换为字符串,使用 getStringVal()
到 return a varchar2
(或者 getClobVal()
如果您有 CLOB 值,这可能会导致其他问题):
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content).getStringVal() as C
-- ^^^^^^^^^^^^^^^
from all_tab_columns
...
如您所见,当由于计数相等而出现联系时,这并没有达到您的预期 - 在您的示例中,发现 T1."col.2"
的不同值(null、10、22 , 45) 其中各出现一次;并且 XMLQuery 将它们全部放在一个结果中。您需要决定在这种情况下您希望发生什么;如果您只想看一个,那么您需要在分析 order by
子句中指定如何决定打破平局。
I actually want to see all results but I expected to see them in different rows
另一种方法是使用 XMLTable 而不是 XMLQuery:
select table_name, column_name, value
from (
select atc.table_name, atc.column_name, x.value, x.value_count,
rank() over (partition by atc.table_name, atc.column_name
order by x.value_count desc) as rnk
from all_tab_columns atc
cross join xmltable(
'/ROWSET/ROW'
passing xmltype(dbms_xmlgen.getxml(
'select "' || column_name || '" as value, count(*) as value_count '
|| 'from ' || table_name || ' '
|| 'group by "' || column_name || '"'))
columns value varchar2(4000) path 'VALUE',
value_count number path 'VALUE_COUNT'
) x
where atc.owner = user
and atc.table_name in ('T1', 'T2', 'T3', 'T4')
)
where rnk = 1;
内部查询将 all_tab_columns
交叉连接到一个 XML 表,该表执行更简单的 dbms_xmlgen.get_xml()
调用以获取每个值及其计数,提取值并作为关系计数来自生成的 XML 的数据,并将排名函数作为该子查询的一部分,而不是在 XML 生成中。如果您 运行 子查询本身,您将看到所有可能的值及其计数,以及每个值的排名。
外部查询然后只过滤排名,并向您显示子查询中排名第一的结果的相关列。
我想为来自 all_tab_columns
的列表获取 column_name
和 table_name
(直到这里这不是问题)以及我想去的每个给定列到原始 table/column 并查看出现次数最多的最高值是什么。
通过下面的查询,我得到了 1 table:
中 1 个列示例的所需值select col1
from (SELECT col1, rank () over (order by count(*) desc) as rnk
from T1
Group by col1
)
where rnk = 1
现在我想要这样的东西:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1;'))
returning content) as C
from all_tab_columns
where owner = 'S1'
and table_name in ('T1', 'T2', 'T3', 'T4')
;
但它不起作用。这是我得到的错误:
ORA-19202: Error occurred in XML processing
ORA-00933: SQL command not properly ended
ORA-06512: at "SYS.DBMS_XMLGEN", line 176
ORA-06512: at line 1
19202. 00000 - "Error occurred in XML processing%s"
*Cause: An error occurred when processing the XML function
*Action: Check the given error message and fix the appropriate problem
我举个例子。例如,这是我的两个 table; T1:
col.1 col.2 col.3
----- ---------- -----
y m1
y 22 m2
n 45 m2
y 10 m5
和 T2:
col.1 col.2 col.3
----- ------- -----
1 germany xxx
2 england xxx
3 germany uzt
3 germany vvx
8 US XXX
所以
- 来自 T1/Col.1 我应该得到 'y'
- 来自 T1/col.3 我应该得到 'm2'
- 来自 T2/col.3 我应该得到 'xxx'
等等。
报告给您的重要错误是:
ORA-00933: SQL command not properly ended
从 dbms_xmlgen.getxml()
调用中的查询中删除分号:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
-------^ no semicolon here
returning content) as C
from all_tab_columns
...
你的 XPath 似乎也是错误的;您正在寻找 /ROWSET/ROW/C
,但 C
是整个表达式的列别名,而不是正在计算的列。您需要在 查询中为列名 添加别名,并在 XPath 中使用它:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
-- ^^^
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
-- ^^^^^^
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content) as C
from all_tab_columns
...
您的样本数据得到:
TABLE_NAME COLUMN_NAME C
------------------------------ ------------------------------ ----------
T1 col.1 y
T1 col.2 224510
T1 col.3 m2
T2 col.1 3
T2 col.2 germany
T2 col.3 xxx
XML查询是 return 一个 XML 类型的结果,您的客户端显然显示为 (XMLTYPE)
。你可能会改变这种行为 - 例如在 Sql 开发人员中,从工具->首选项->数据库->高级->DIsplay XMl 网格中的值。但是您也可以将结果转换为字符串,使用 getStringVal()
到 return a varchar2
(或者 getClobVal()
如果您有 CLOB 值,这可能会导致其他问题):
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content).getStringVal() as C
-- ^^^^^^^^^^^^^^^
from all_tab_columns
...
如您所见,当由于计数相等而出现联系时,这并没有达到您的预期 - 在您的示例中,发现 T1."col.2"
的不同值(null、10、22 , 45) 其中各出现一次;并且 XMLQuery 将它们全部放在一个结果中。您需要决定在这种情况下您希望发生什么;如果您只想看一个,那么您需要在分析 order by
子句中指定如何决定打破平局。
I actually want to see all results but I expected to see them in different rows
另一种方法是使用 XMLTable 而不是 XMLQuery:
select table_name, column_name, value
from (
select atc.table_name, atc.column_name, x.value, x.value_count,
rank() over (partition by atc.table_name, atc.column_name
order by x.value_count desc) as rnk
from all_tab_columns atc
cross join xmltable(
'/ROWSET/ROW'
passing xmltype(dbms_xmlgen.getxml(
'select "' || column_name || '" as value, count(*) as value_count '
|| 'from ' || table_name || ' '
|| 'group by "' || column_name || '"'))
columns value varchar2(4000) path 'VALUE',
value_count number path 'VALUE_COUNT'
) x
where atc.owner = user
and atc.table_name in ('T1', 'T2', 'T3', 'T4')
)
where rnk = 1;
内部查询将 all_tab_columns
交叉连接到一个 XML 表,该表执行更简单的 dbms_xmlgen.get_xml()
调用以获取每个值及其计数,提取值并作为关系计数来自生成的 XML 的数据,并将排名函数作为该子查询的一部分,而不是在 XML 生成中。如果您 运行 子查询本身,您将看到所有可能的值及其计数,以及每个值的排名。
外部查询然后只过滤排名,并向您显示子查询中排名第一的结果的相关列。