我经常需要在多个表中搜索给定值的精确或类似匹配。 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%';
我不想创建VIEW
或SELECT
(带UNION
)因为我只想执行每个查询,直到找到第一个结果。如果我找到了结果,请停止,以免造成不必要的执行开销。
如何使用PL / SQL传递参数并循环遍历这些语句?嵌套异常块?
在我的环境中,我希望只在一个表中找到结果,或者根本找不到结果。我的数据库是Oracle 10g(备用我),我正在使用SQL Developer 4.1.5。
答案 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