2012-04-20 39 views
2

我想在SYS.ALL_ARGUMENTS上創建向後兼容的查詢。在Oracle 11g中,添加了有用的ALL_ARGUMENTS.DEFAULTED列。現在,如果我對Oracle 10g運行此查詢:選擇Oracle字典視圖中可能不存在的列

SELECT defaulted FROM all_arguments 

當然,我收到一個錯誤。

ORA-00904: 「SYS」 「ALL_ARGUMENTS」 「缺位」:無效的標識符

我想要做的是這樣的:

SELECT CASE WHEN column_exists("defaulted") 
      THEN defaulted 
      ELSE 'N' 
     END 
FROM all_arguments 

甚至更​​好

SELECT evaluate_column_on_current_row(column_name   => "defaulted", 
             default_if_not_exists => 'N') 
FROM all_arguments 

有沒有辦法在單個SQL查詢中做到這一點,而不訴諸PL/SQL?或者,我應該先檢查Oracle版本,如下所示:

SELECT count(*) 
FROM all_tab_cols 
WHERE owner = 'SYS' 
AND table_name = 'ALL_ARGUMENTS' 
AND column_name = 'DEFAULTED' 
+0

你會得到什麼錯誤? – Arion 2012-04-20 09:22:16

+0

@Arion:ORA-00904 ...查看更新後的問題 – 2012-04-20 09:26:37

回答

2

引用不存在的列的查詢無法生成有效的計劃。

您需要選擇提交的查詢總是有效的方法。是動態生成/執行它們,還是其他一些方法。

但是,如果您提交了一個要解析的查詢,並且它在existant表上包含一個不存在的字段,那麼解析器將把它扔回給您。

+0

是的,但我認爲可能有一些系統函數用於評估投影中當前行的表達式。 顯然,這並不是執行計劃生成的最佳選擇,但我不明白爲什麼原則上不應該這麼做......我已經給該問題添加了一個更好的示例,其中包含完整的動態列名稱評估 – 2012-04-20 09:33:21

+0

@ LukasEder - 簡單地說,因爲SQL被編譯。如果您想要間接級別,那麼在運行時查看字段名稱的位置,解決方案*就是*動態SQL。這件事情是由很多原因導致的;最簡單的是,當提交查詢被解析和編譯時,檢查各種統計數據和其他細節(索引,約束,選擇性等)以形成計劃。那個計劃然後被固定用於*那個查詢。如果您提交了一個甚至略有不同的查詢,您會得到一個新的計劃。這只是SQL的工作方式。對於你的第一個例子,動態SQL似乎完全適合我。 – MatBailie 2012-04-20 12:57:54