Mys*_*ose 5 oracle oracle-10g cte view
再会,
这个难倒我了。我有一个相当讨厌的开发人员查询,我想将其存储在非物化的 Oracle 视图中。视图本身的文本在这里列出有点长,但它编译得很好并生成正确的结果集。视图查询本身使用 CTE 以及两个手动逆透视(UNPIVOT 运算符在 Oracle 10 中不可用)和相当多的 UNION。这个想法是重复使用每个 CTE '中间' 查询来提取各种聚合,否则这些聚合在单个查询中是不可能的(糟糕的数据库设计,不幸的是我无法控制)。需要许多聚合,这是我在速度、可维护性和可读性/自文档化代码方面可以提出的最佳解决方案。
现在,当我做一个简单的
SELECT *
FROM myView;
Run Code Online (Sandbox Code Playgroud)
但是,每当我尝试过滤结果时,WHERE 子句似乎都被忽略了。类似的东西
SELECT *
FROM myView
WHERE DATA_TYPE = 3; -- <== There is no DATA_TYPE = 3 in the result set
Run Code Online (Sandbox Code Playgroud)
仍然返回所有行,而它应该什么都不返回。涉及任何其他列的其他谓词似乎也被忽略。知道什么可能导致这种情况吗?上面的 SELECT 执行得很好,没有给出错误。
作为参考,DBMS 是 Oracle 10g。
提前感谢您的任何帮助。
编辑:
仍然展示相同行为的视图查询的精简版本如下(在 CTE 的内部和外部部分有更多的查询,为了紧凑,我只包含了两个内部和一个外部):
CREATE OR REPLACE VIEW FSA.FSA_V_DB_TOTALS
(
DATA_CATEGORY, DATA_TYPE, HUMAN_STRING, ELEMENT_NAME, ELEMENT_VAL,
CLASS_CD, REGION, CNTY, DIST, TRA, FRAN, PROP
)
AS
WITH
--Queries to generate intermediate result sets
--Distribution TRA
DIST_TRA AS (
SELECT 'DISTRIBUTION - TRA' AS DATA_CATEGORY,
1 AS DATA_TYPE,
CLASS_CD AS CLASS_CD,
NULL AS REGION,
CNTY_CD AS CNTY,
NULL AS DIST,
TRA_CD AS TRA,
NULL AS FRAN,
NULL AS PROP,
TEXT AS HUMAN_STRING,
DECODE(UNPIVOT_ROW, 1, 'CIRCUIT MILEAGE',
2, 'WIRE MILEAGE',
3, 'DUCT MILEAGE',
'N/A') AS ELEMENT_NAME,
DECODE(UNPIVOT_ROW, 1, CIRCT_FT,
2, WIRE_FT,
3, DUCT_FT,
'N/A') AS ELEMENT_VAL
FROM (
SELECT T1.CLASS_CD AS CLASS_CD,
T1.CNTY_CD AS CNTY_CD,
T2.TRA_CD AS TRA_CD,
DECODE(COALESCE(T2.TRA_CD,
T1.CNTY_CD,
T1.CLASS_CD), NULL, 'DISTRIBUTION TRA TOTAL',
T2.TRA_CD, 'TRA ' || T2.TRA_CD || ' TOTAL',
T1.CNTY_CD, 'COUNTY ' || T1.CNTY_CD || ' TOTAL',
T1.CLASS_CD, 'CLASS ' || T1.CLASS_CD || ' TOTAL') AS TEXT,
SUM(T2.CIRCT_FT_QTY) AS CIRCT_FT,
SUM(T2.WIRE_FT_QTY) AS WIRE_FT,
SUM(T2.DUCT_FT_QTY) AS DUCT_FT
FROM FSA.FSA001_DISTRIBUT T1
INNER JOIN
FSA.FSA002_DIST_TRA T2 ON T1.SERIAL_NO = T2.SERIAL_NO
GROUP BY GROUPING SETS ((T1.CLASS_CD, T1.CNTY_CD, T2.TRA_CD),
(T1.CLASS_CD, T1.CNTY_CD),
(T1.CLASS_CD),
())
),(
SELECT level AS UNPIVOT_ROW FROM DUAL CONNECT BY level <= 3
)
),
--Distribution Fran
DIST_FRAN AS (
SELECT 'DISTRIBUTION - FRAN' AS DATA_CATEGORY,
2 AS DATA_TYPE,
CLASS_CD AS CLASS_CD,
NULL AS REGION,
CNTY_CD AS CNTY,
DIST_CD AS DIST,
NULL AS TRA,
FRAN_CD AS FRAN,
PROP_CD AS PROP,
TEXT AS HUMAN_STRING,
DECODE(UNPIVOT_ROW, 1, 'POLE MILEAGE',
2, 'ST LIGHT MILEAGE',
'N/A') AS ELEMENT_NAME,
DECODE(UNPIVOT_ROW, 1, POLE_FT,
2, SL_FT,
'N/A') AS ELEMENT_VAL
FROM (
SELECT T1.CLASS_CD AS CLASS_CD,
T1.CNTY_CD AS CNTY_CD,
T1.DIST_CD AS DIST_CD,
T3.FRNCHSE_CD AS FRAN_CD,
T3.PROPRTY_CD AS PROP_CD,
DECODE(COALESCE(T3.PROPRTY_CD,
T3.FRNCHSE_CD,
T1.DIST_CD,
T1.CNTY_CD,
T1.CLASS_CD), NULL, 'DISTRIBUTION FRAN TOTAL',
T3.PROPRTY_CD, 'PROPERTY ' || T3.PROPRTY_CD || ' TOTAL',
T3.FRNCHSE_CD, 'FRAN ' || T3.FRNCHSE_CD || ' TOTAL',
T1.DIST_CD, 'DISTRICT ' || T1.DIST_CD || ' TOTAL',
T1.CNTY_CD, 'COUNTY ' || T1.CNTY_CD || ' TOTAL',
T1.CLASS_CD, 'CLASS ' || T1.CLASS_CD || ' TOTAL') AS TEXT,
SUM(T3.POLE_FT_QTY) AS POLE_FT,
SUM(T3.ST_LIGHT_FT_QTY) AS SL_FT
FROM FSA.FSA001_DISTRIBUT T1
INNER JOIN
FSA.FSA003_DIST_FRAN T3 ON T1.SERIAL_NO = T3.SERIAL_NO
GROUP BY GROUPING SETS ((T1.CLASS_CD, T1.CNTY_CD, T1.DIST_CD, T3.FRNCHSE_CD, T3.PROPRTY_CD),
(T1.CLASS_CD, T1.CNTY_CD, T1.DIST_CD, T3.FRNCHSE_CD),
(T1.CLASS_CD, T1.CNTY_CD, T1.DIST_CD),
(T1.CLASS_CD, T1.CNTY_CD),
(T1.CLASS_CD),
())
),(
SELECT level AS UNPIVOT_ROW FROM DUAL CONNECT BY level <= 2
)
)
--Queries to generate final result set based on CTE intermediate queries
--Subtotals / System totals for Dist-TRA, Dist-Fran, Trans-TRA, Trans-Fran
SELECT DATA_CATEGORY, DATA_TYPE, HUMAN_STRING, ELEMENT_NAME, ELEMENT_VAL,
CLASS_CD, REGION, CNTY, DIST, TRA, FRAN, PROP
FROM (SELECT * FROM DIST_TRA
UNION ALL
SELECT * FROM DIST_FRAN)
ORDER BY DATA_CATEGORY, CLASS_CD, REGION, CNTY, DIST, NVL2(TRA, TRA, FRAN), ELEMENT_NAME, HUMAN_STRING
/
Run Code Online (Sandbox Code Playgroud)
编辑2:
从带有谓词的视图中进行选择的完整解释计划。请注意,DBMS 不会在顶级 SELECT 上显示任何谓词。
SQL> SELECT * FROM FSA.FSA_V_DB_TOTALS WHERE DATA_TYPE = 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 3417880006
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 88095 | 6194K| | 5232 (3)| 00:01:03 |
| 1 | VIEW | FSA_V_DB_TOTALS | 88095 | 6194K| | 5232 (3)| 00:01:03 |
| 2 | SORT ORDER BY | | 88095 | 6194K| 17M| 5232 (3)| 00:01:03 |
| 3 | VIEW | | 88095 | 6194K| | 3721 (4)| 00:00:45 |
| 4 | UNION-ALL | | | | | | |
| 5 | MERGE JOIN CARTESIAN | | 1995 | 150K| | 1492 (6)| 00:00:18 |
| 6 | VIEW | | 1 | 13 | | 2 (0)| 00:00:01 |
|* 7 | CONNECT BY WITHOUT FILTERING| | | | | | |
| 8 | FAST DUAL | | 1 | | | 2 (0)| 00:00:01 |
| 9 | BUFFER SORT | | 1995 | 124K| | 1492 (6)| 00:00:18 |
| 10 | VIEW | | 1995 | 124K| | 1490 (6)| 00:00:18 |
| 11 | SORT GROUP BY ROLLUP | | 1995 | 59850 | | 1490 (6)| 00:00:18 |
|* 12 | HASH JOIN | | 408K| 11M| 3280K| 1447 (3)| 00:00:18 |
| 13 | TABLE ACCESS FULL | FSA001_DISTRIBUT | 152K| 1488K| | 292 (2)| 00:00:04 |
| 14 | TABLE ACCESS FULL | FSA002_DIST_TRA | 408K| 7980K| | 362 (5)| 00:00:05 |
| 15 | MERGE JOIN CARTESIAN | | 86100 | 5969K| | 2229 (3)| 00:00:27 |
| 16 | VIEW | | 1 | 13 | | 2 (0)| 00:00:01 |
|* 17 | CONNECT BY WITHOUT FILTERING| | | | | | |
| 18 | FAST DUAL | | 1 | | | 2 (0)| 00:00:01 |
| 19 | BUFFER SORT | | 86100 | 4876K| | 2229 (3)| 00:00:27 |
| 20 | VIEW | | 86100 | 4876K| | 2227 (3)| 00:00:27 |
| 21 | SORT GROUP BY ROLLUP | | 86100 | 2438K| 14M| 2227 (3)| 00:00:27 |
|* 22 | HASH JOIN | | 267K| 7582K| 3728K| 1006 (3)| 00:00:13 |
| 23 | TABLE ACCESS FULL | FSA001_DISTRIBUT | 152K| 1935K| | 293 (3)| 00:00:04 |
| 24 | TABLE ACCESS FULL | FSA003_DIST_FRAN | 267K| 4183K| | 166 (5)| 00:00:02 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
7 - filter(LEVEL<=3)
12 - access("T2"."SERIAL_NO"="T1"."SERIAL_NO")
17 - filter(LEVEL<=2)
22 - access("T1"."SERIAL_NO"="T3"."SERIAL_NO")
SQL>
Run Code Online (Sandbox Code Playgroud)
经过一些尝试和错误,我找到了罪魁祸首。事实证明,这与视图本身无关。尝试将 where 子句直接手动推入查询也会产生相同的错误结果。
事实证明,问题是由内部查询中的 CONNECT BY 子句引起的。我的怀疑(可能是完全错误的)是这与 Oracle 10g 无法处理递归 CTE 有关。如果有人有更多关于为什么会发生这种情况的信息,我洗耳恭听。
我能够通过移动来解决这个问题
SELECT level AS UNPIVOT_ROW FROM DUAL CONNECT BY level <= 3
Run Code Online (Sandbox Code Playgroud)
子查询到它自己的 CTE 块并正常从中进行选择。下面我包含了上述损坏查询的(精简的)工作版本。
CREATE OR REPLACE VIEW FSA.FSA_V_DB_TOTALS_2
(...)
AS
WITH
--Queries to generate intermediate result sets
--'NUMBERS' CTE block to work around Oracle 10g limitation wherein WHERE
-- clause is ignored if CONNECY BY is directly written into inner queries.
-- NOTE: the size limitation (currently 10) only needs to be larger than
-- or equal to the largest value needed.
NUMBERS AS (
SELECT level AS UNPIVOT_ROW
FROM DUAL CONNECT BY level <=10
),
--Distribution TRA
DIST_TRA AS (
SELECT ...
FROM (
SELECT ...
FROM FSA.FSA001_DISTRIBUT T1
INNER JOIN
FSA.FSA002_DIST_TRA T2 ON T1.SERIAL_NO = T2.SERIAL_NO
GROUP BY GROUPING SETS (...)
),(
SELECT UNPIVOT_ROW FROM NUMBERS WHERE UNPIVOT_ROW <= 3 -- <== THIS
)
),
--Distribution Fran
DIST_FRAN AS (
SELECT ...
FROM (
SELECT ...
FROM FSA.FSA001_DISTRIBUT T1
INNER JOIN
FSA.FSA003_DIST_FRAN T3 ON T1.SERIAL_NO = T3.SERIAL_NO
GROUP BY GROUPING SETS (...)
),(
SELECT UNPIVOT_ROW FROM NUMBERS WHERE UNPIVOT_ROW <= 2 -- <== THIS AS WELL
)
)
--Queries to generate final result set based on CTE intermediate queries
--Subtotals / System totals for Dist-TRA, Dist-Fran, Trans-TRA, Trans-Fran
SELECT ...
FROM (SELECT * FROM DIST_TRA
UNION ALL
SELECT * FROM DIST_FRAN)
Run Code Online (Sandbox Code Playgroud)