2012-08-08 72 views
0

我已經「繼承」數據庫應用程序(基於Oracle 10g數據庫上,並用Delphi編寫的),它必須作出一些決定如下:Oracle數據庫 - 如果查詢1的結果爲空試QUERY2

Do Query1. 
If the result set is empty, do Query2. 

查詢有SELECT查詢具有相同的輸出列,有時類似(情況1),有時不同(情況2)輸入(FROM)和條件(WHERE)。

情況1:有時所不同的是:col like 'x'(或COL = 'X')變爲col like '%'

  • 性能:最好使用兩個不同的查詢(col = 'x'和其他沒有它的查詢)。
  • 可維護性:col like :param是更好,因爲它不需要2個查詢
  • 折中的方案:AND (col = 'x' OR :param = 1)

案例2:還有一次,我必須用一個完全地不同QUERY2如果在沒有數據Query1的結果集。


從搜索stackoverflow,我知道了幾種解決我的問題的互聯網:

  1. 使用兩個SQL查詢:讓程序做的工作,而不是數據庫(但需要查詢數據庫而不是僅一次兩次)

    result = executeQuery(Query1) 
    if (isEmpty(result)) 
    result = executeQuery(Query2) 
    
  2. 使用UNION:讓Oracle做的所有工作(但需要執行查詢1次):

    Query1 UNION ALL Query 2 WHERE NOT EXISTS (Query 1) 
    
  3. 使用PL/SQL:讓Oracle做的大部分工作(但我讀的地方,查詢是這樣每次編譯)

    begin 
    Query1; 
    exception when no_data_found then 
    Query2; 
    end; 
    

我的問題分別是:

  1. 是否有其他(更好的)解決方案?
  2. 你(作爲比我更有經驗的數據庫用戶)使用什麼?
  3. 什麼是(dis)優點?
  4. 有什麼注意事項?

回答

1

在很多情況下,你可以通過使用更少的嚴格WHERE條款避免UNION,但包括ORDER BY子句,以便更好的匹配結果首次出現。如果必要的話,可以使用ROWNUM虛列限制結果的第一位。

例如,而不是

BEGIN 
    SELECT * INTO myrec FROM mytable WHERE xxx = 'x'; 
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
    SELECT * INTO myrec FROM mytable WHERE xxx like '%x%'; 
END; 

你可以寫

SELECT * INTO myrec FROM (
    SELECT * FROM mytable WHERE X like '%x%' 
    ORDER BY CASE when xxx='x' THEN 1 ELSE 2 END 
) WHERE ROWNUM=1; 

注意嵌套SELECT報表;這是必要的,因爲否則,WHERE ROWNUM=1子句將限制ORDER BY發生之前的結果集。