2016-12-23 50 views
1
SELECT in_ev.type, pl.name, in_ev.year 
FROM places pl INNER JOIN (SELECT e.type, e.place_id, e.year 
          FROM events e)in_ev ON in_ev.place_id=pl.place_id 
WHERE EXISTS (SELECT 1 FROM in_ev sub_ev WHERE sub_ev.year=1994) 

我想了解如何處理內聯視圖,以及爲什麼我們不能將它們用作where子句子查詢中的「源表」。當我嘗試運行此查詢時,我得到ORA-00942:表或視圖不存在內聯視圖限制

上面的代碼僅用於說明的原因。

普通表和內聯視圖之間存儲和處理的確切區別是什麼?

回答

2

where子句中的子查詢無法看到內嵌視圖,我想你已經想通了;這是一個範圍問題,真的。沒有存儲空間,以及它如何在內存中管理和處理有點落後於優化器 - 例如,它可能會大幅改寫事物。我猜想,在評估內嵌視圖之前,子查詢可能會進行邏輯評估。

由於解析器在查詢被實際執行之前拋出ORA-00942,因此如何處理內聯視圖是一個有爭議的問題。

您可以使用,而不是子查詢分解:

WITH in_ev AS (
    SELECT e.type, e.place_id, e.year 
    FROM events e 
) 
SELECT in_ev.type, pl.name, in_ev.year 
FROM places pl INNER JOIN in_ev ON in_ev.place_id=pl.place_id 
WHERE EXISTS (SELECT 1 FROM in_ev sub_ev WHERE sub_ev.year=1994) 

這看起來很奇怪這樣一個人爲的例子,但你acknowleged,它在這個問題說明。 where子句中的子查詢可以看到CTE - 它在解析器的範圍內。

正如@mathguy在評論中指出的那樣,優化器可能仍然將CTE視爲子查詢,但這通常不是您需要擔心的事情 - 特別是如果您只是想避免出現錯誤。

+1

要添加到Alex的解釋中,並進一步回答有關評估和存儲的問題:當Optimizer看到因式分解子查詢(WITH子句中的「視圖」)時,可以自由考慮兩個選項並選擇它認爲的那個效率更高。一種是將它視爲內聯視圖(在FROM和WHERE子句中就地評估它);或者,它可以將其視爲臨時全局表,只計算一次,保存並使用它,就像它可能使用存儲的表一樣,在查詢的其餘部分使用它。 CBO將選擇哪個選項取決於幾件事情。 – mathguy