请帮助我确认以下说明的行为是一个错误,或者明确说明为什么是正确的。我很可能误解了一些概念,但是现在对我而言,这似乎是一个错误。
下面的所有示例均尽可能简化以说明问题的核心。实际情况非常复杂,因此仅可接受与查询构造原理相关的一般答案和变通办法。 欢迎您在评论中提出澄清的问题,我会尽力回答。 感谢您的关注。:)
为什么在子查询的最后一个示例(示例5)collection中,(select count(1) ...从第一行的实例 映射到表的所有行,而预期结果是将每个collection实例映射到它自己的行? 同时collections在cardinality(...)表达式中使用正确选择。 如果以此方式构造查询中from或where查询中使用的集合,则存在相同的情况(示例中未涉及)。
collection
(select count(1) ...
collections
cardinality(...)
from
where
(SQLFiddle)
create or replace type TabType0 as table of varchar2(100) / create table Table0( tab_str_field varchar2(100), tab_field TabType0) nested table tab_field store as tab_field_table / insert into table0 (tab_str_field, tab_field) values ( 'A', cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual ) as TabType0) ) / insert into table0 (tab_str_field, tab_field) values ( 'B', cast(multiset( select 'B' from dual union all select 'C' from dual ) as TabType0) ) / insert into table0 (tab_str_field, tab_field) values ( 'C', cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual union all select 'D' from dual ) as TabType0) ) / insert into table0 (tab_str_field, tab_field) values ( 'D', cast(multiset( select 'A' from dual ) as TabType0) ) / select 'Initial table data' caption from dual / select * from table0 /
表数据:
| TAB_STR_FIELD | TAB_FIELD | ----------------------------- | A | A,B,C | | B | B,C | | C | A,B,C,D | | D | A |
示例1 (SQLFiddle)-使用嵌套表字段- 确定
select 'Work with nested table - OK' caption from dual / select tab_field tab_field, -- cardinality cardinality(tab_field) tab_cardinality, -- select from table field of current row (select count(1) from table(tab_field)) tab_count, -- select from field of current row while joining -- with another field of same row ( select column_value from table(tab_field) where column_value = tab_str_field ) same_value from table0 /
结果:
| TAB_FIELD | TAB_CARDINALITY | TAB_COUNT | SAME_VALUE | -------------------------------------------------------- | A,B,C | 3 | 3 | A | | B,C | 2 | 2 | B | | A,B,C,D | 4 | 4 | C | | A | 1 | 1 | (null) |
示例2 (SQLFiddle)-单独处理构造的源数据- 确定
select 'Work with constructed source data alone - OK' caption from dual / with table_data_from_set as ( select 'A' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'B' tab_str_field, cast(multiset( select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'C' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual union all select 'D' from dual ) as TabType0) tab_field from dual union all select 'D' tab_str_field, cast(multiset( select 'A' from dual ) as TabType0) tab_field from dual ) select tab_field tab_field, -- cardinality cardinality(tab_field) tab_cardinality, -- select from table field of current row (select count(1) from table(tab_field)) tab_count, -- select from field of current row while joining -- with another field of same row ( select column_value from table(tab_field) where column_value = tab_str_field ) same_value from table_data_from_set /
示例3 (SQLFiddle)-具有在其中构造的多集的联接表WITH- 确定
WITH
select 'Join table with multisets constructed in WITH - OK' caption from dual / with table_data_from_set as ( select 'A' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'B' tab_str_field, cast(multiset( select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'C' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual union all select 'D' from dual ) as TabType0) tab_field from dual union all select 'D' tab_str_field, cast(multiset( select 'A' from dual ) as TabType0) tab_field from dual ) select table0.tab_field table0_tab_field, table_data_from_set.tab_field set_tab_field, -- cardinality cardinality(table0.tab_field) table0_tab_cardinality, cardinality(table_data_from_set.tab_field) set_tab_cardinality, -- select from table field of current row (select count(1) from table(table_data_from_set.tab_field)) set_tab_count, -- select from field of current row while joining -- with another field of same row ( select column_value from table(table_data_from_set.tab_field) where column_value = table0.tab_str_field ) same_value from table0, table_data_from_set where table_data_from_set.tab_str_field = table0.tab_str_field /
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE | ---------------------------------------------------------------------------------------------------------------- | A,B,C | A,B,C | 3 | 3 | 3 | A | | B,C | B,C | 2 | 2 | 2 | B | | A,B,C,D | A,B,C,D | 4 | 4 | 4 | C | | A | A | 1 | 1 | 1 | (null) |
示例4 (SQLFiddle)-具有在WITH +子查询中构造的多集的联接表- 确定
select 'Join table with multisets constructed in WITH and subquery - OK' caption from dual / with table_data_from_set as ( select 'A' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'B' tab_str_field, cast(multiset( select 'B' from dual union all select 'C' from dual ) as TabType0) tab_field from dual union all select 'C' tab_str_field, cast(multiset( select 'A' from dual union all select 'B' from dual union all select 'C' from dual union all select 'D' from dual ) as TabType0) tab_field from dual union all select 'D' tab_str_field, cast(multiset( select 'A' from dual ) as TabType0) tab_field from dual ) select table0_tab_field table0_tab_field, set_tab_field set_tab_field, -- cardinality cardinality(table0_tab_field) table0_tab_cardinality, cardinality(set_tab_field) set_tab_cardinality, -- select from table field of current row (select count(1) from table(set_tab_field)) set_tab_count, -- select from field of current row while joining -- with another field of same row ( select column_value from table(set_tab_field) where column_value = table0_tab_str_field ) same_value from ( select table0.tab_str_field table0_tab_str_field, table0.tab_field table0_tab_field, table_data_from_set.tab_str_field set_tab_str_field, table_data_from_set.tab_field set_tab_field from table0, table_data_from_set where table_data_from_set.tab_str_field = table0.tab_str_field ) /
实施例5 (SQLFiddle) -连接表与在飞行构造多重集- FAILED
select 'Join table with multisets constructed on the fly - FAIL (set_tab_count wrong)' caption from dual / with string_set as ( select 'A' str_field from dual union all select 'B' str_field from dual union all select 'C' str_field from dual union all select 'D' str_field from dual union all select 'E' str_field from dual ) select table0_tab_field table0_tab_field, set_tab_field set_tab_field, -- cardinality cardinality(table0_tab_field) table0_tab_cardinality, cardinality(set_tab_field) set_tab_cardinality, -- select from table field of current row (select count(1) from table(set_tab_field)) set_tab_count, -- select from field of current row while joining -- with another field of same row ( select column_value from table(set_tab_field) where column_value = table0_tab_str_field ) same_value from ( select table0.tab_str_field table0_tab_str_field, table0.tab_field table0_tab_field, ( cast(multiset( select string_set.str_field from string_set, table(table0.tab_field) tab_table where string_set.str_field = tab_table.column_value ) as TabType0) ) set_tab_field from table0 ) /
结果(set_tab_count列中的所有值都相同- _ 错误!_ ):
set_tab_count
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE | ---------------------------------------------------------------------------------------------------------------- | A,B,C | A,B,C | 3 | 3 | 3 | A | | B,C | B,C | 2 | 2 | 3 | B | | A,B,C,D | A,B,C,D | 4 | 4 | 3 | C | | A | A | 1 | 1 | 3 | (null) |
实例1
BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production PL/SQL Release 11.2.0.3.0 - Production CORE 11.2.0.3.0 Production TNS for IBM/AIX RISC System/6000: Version 11.2.0.3.0 - Production NLSRTL Version 11.2.0.3.0 - Production
实例2
BANNER -------------------------------------------------------------------------------- Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production PL/SQL Release 11.2.0.2.0 - Production CORE 11.2.0.2.0 Production TNS for 32-bit Windows: Version 11.2.0.2.0 - Production NLSRTL Version 11.2.0.2.0 - Production
SQLFiddle与所有查询一起。
这是一个错误。/*+ NO_MERGE */在上一个示例中,向第二个嵌入式视图添加提示将产生预期的结果。有关示例,请参见此SQL Fiddle。不管查询如何,该提示都不应更改结果。您还可以进行其他一些看似无关的更改,这些更改将生成正确的结果,例如删除某些列,或ROWNUM在中间添加未使用的列。
/*+ NO_MERGE */
ROWNUM
Oracle正在重新编写查询以对其进行优化,但是这样做有误。通过跟踪查询,您可能会获得更多信息,但是我怀疑您是否能够真正解决该问题。现在就解决它,并向Oracle提交服务请求,这样他们就可以创建错误并最终对其进行修复。