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

问题描述 投票:0回答:2

我经常需要在多个表中搜索给定值的精确或类似匹配。 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。

sql oracle
2个回答
2
投票

1.

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

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

2.

标量子查询是一个返回单个列和单个行的查询(如果它返回多行,它应该是标量查询,您将收到运行时错误) - 或者它可能不返回任何行。标量子查询通常用于通常可以使用“表达式”的地方;在这些情况下,子查询返回的一行一列的值将用作所需的“表达式”。如果返回的“value”为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 

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 ;
© www.soinside.com 2019 - 2024. All rights reserved.