2012-08-08 135 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发生之前的结果集。