Oracle - 循环选择语句直到找到结果

时间:2018-03-05 16:16:45

标签: sql oracle

我经常需要在多个表中搜索给定值的精确或类似匹配。 SELECT语句总是相同的,但我搜索的值总是不同。

SELECT * FROM employees WHERE first_name = 'foobar';
SELECT * FROM jobs WHERE job_title LIKE 'foobar%';
SELECT * FROM departments WHERE department_name LIKE '%foobar';
SELECT * FROM locations WHERE city LIKE '%foobar%';

我不想创建VIEWSELECT(带UNION)因为我只想执行每个查询,直到找到第一个结果。如果我找到了结果,请停止,以免造成不必要的执行开销。

如何使用PL / SQL传递参数并循环遍历这些语句?嵌套异常块?

在我的环境中,我希望只在一个表中找到结果,或者根本找不到结果。我的数据库是Oracle 10g(备用我),我正在使用SQL Developer 4.1.5。

2 个答案:

答案 0 :(得分:3)

SQL查询返回一组固定的列。因此,您的结构假定所有表都具有相同的列。我怀疑这是实际情况,所以让我假设您知道这一点,并且您使用SELECT *作为简写。

您不能短路SQL查询。但是,你可以安排它们,所以基本上什么都没做。我们的想法是以逐步的方式使用NOT EXISTS。当基础表有数据时,这应该非常快,因此实际上跳过了CTE逻辑。

这是一种使用CTE的方法

with e as (
      SELECT *
      FROM employees
      WHERE first_name = 'foobar'
     ),
     j as (
      SELECT *
      FROM jobs
      WHERE job_title LIKE 'foobar%' AND
            NOT EXISTS (SELECT 1 FROM e)
    ),
    d as (
     SELECT *
     FROM departments
     WHERE department_name LIKE '%foobar' AND
           NOT EXISTS (SELECT 1 FROM e) AND
           NOT EXISTS (SELECT 1 FROM j)
    ),
    l as (
     SELECT *
     FROM locations WHERE city LIKE '%foobar%' AND
           NOT EXISTS (SELECT 1 FROM e) AND
           NOT EXISTS (SELECT 1 FROM j) AND
           NOT EXISTS (SELECT 1 FROM d)
    )
SELECT e.* FROM e UNION ALL
SELECT j.* FROM j UNION ALL
SELECT d.* FROM e UNION ALL
SELECT l.* FROM l ;

答案 1 :(得分:2)

1

COALESCE()是Oracle标准函数,Oracle按照标准的要求实现。该函数接受一个或多个参数,所有相同的数据类型(否则解析器将抛出错误),并返回第一个非NULL参数,如果所有参数都为NULL,则返回NULL。

重要的是,查询引擎将计算第一个参数,如果它不是NULL,它将返回并且它不会计算其他参数。如果第一个参数是NULL但是第二个参数不是,它将返回第二个参数,它将停止。这被称为"短路评估。"

2

标量子查询是一个返回单个列和单个行的查询(如果它返回多行,它应该是标量查询,您将收到运行时错误) - 或者它可能不返回任何行。标量子查询通常用于"表达式"一般情况下可以使用;在这些情况下,子查询返回的一行一列的值将用作所需的"表达式"。如果"值"返回为NULL,或者如果子查询没有返回任何行,则表达式将为NULL。

3

您可以使用这些观察来解决您的问题。 警告虽然:你说过"搜索"参数只能在一个表中找到。如果在一个表中找到它,但是你必须提取的相应值是NULL,那么COALESCE不知道应该是搜索的结束,它仍将计算所有标量子查询。

以下是使用此想法的示例。由于我没有你的表,我在SCOTT模式中为EMP和DEPT表编写了它。输入是一个数字,我对它进行了硬编码,但你可以使它成为一个绑定变量(你可以编写更复杂的WHERE子句)。我搜索员工编号为10的员工姓名,如果没有找到,我想要部门编号为10的部门名称。

select coalesce (
                  (select ename from emp  where empno  = 10),
                  (select dname from dept where deptno = 10)
                ) as name from dual;

NAME         
--------------
ACCOUNTING