Oracle DB - 如果Query1的结果为空,请尝试Query2

时间:2012-08-08 10:50:18

标签: oracle

我'继承'了一个数据库应用程序(基于Oracle 10g数据库,用Delphi编写),必须做出如下决定:

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:如果Query1的结果集中没有数据,我还需要使用完全不同的Query2。


从搜索stackoverflow和互联网上我知道我的问题的几个解决方案:

  1. 使用两个SQL查询:让程序执行工作而不是数据库(但需要查询数据库两次而不是一次)

    result = executeQuery(Query1)
    if (isEmpty(result))
    result = executeQuery(Query2)
    
  2. 使用UNION:让Oracle完成所有工作(但需要执行两次Query1):

    Query1 UNION ALL Query 2 WHERE NOT EXISTS (Query 1)
    
  3. 使用PL / SQL:让Oracle完成大部分工作(但我在某处读到每次都以这种方式编译查询)

    begin
     Query1;
    exception when no_data_found then
     Query2;
    end;
    

  4. 我的问题是:

    1. 还有其他(更好)的解决方案吗?
    2. 您(作为比我更有经验的数据库用户)会使用什么?
    3. (dis)优势是什么?
    4. 有什么警告?

1 个答案:

答案 0 :(得分:1)

在许多情况下,您可以通过使用较不严格的UNION子句来避免WHERE,但包含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发生之前的结果集。