0

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

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

查询是SELECT具有相同输出列、有时相似(案例 1)、有时不同(案例 2)输入 (FROM) 和条件 (WHERE) 的查询。

情况 1:有时差异是:col like 'x'(or 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;
    

我的问题是:

  1. 还有其他(更好的)解决方案吗?
  2. 您(作为比我更有经验的数据库用户)会使用什么?
  3. 有什么(缺点)优点?
  4. 有什么注意事项?
4

1 回答 1

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发生之前限制结果集。

于 2012-08-08T11:55:05.957 回答