这些片段是等价的吗? (NVL 与例外)
Posted
技术标签:
【中文标题】这些片段是等价的吗? (NVL 与例外)【英文标题】:Are these snippets equivalents? (NVL vs Exception) 【发布时间】:2012-10-11 12:59:30 【问题描述】:当没有找到数据时,我对管理基于 sql 语句的变量赋值的情况存在疑问。首先,这些块是等价的吗?如果这是真的,是两者中的一个更好吗?
declare
nonsense number;
begin
select nvl((select 1 from dual where 1 <> 1),2) into nonsense from dual;
dbms_output.put_line(nonsense);
end;
declare
nonsense number;
begin
begin
select 1 into nonsense from dual where 1<>1;
exception when no_data_found then
nonsense := 2;
end;
dbms_output.put_line(nonsense);
end;
【问题讨论】:
【参考方案1】:短答案是,长答案,在这种情况下nvl更快,如果没有找到结果值就在de select内部,在异常中它首先执行select,然后在调用异常的过程之后。在这种情况下,nvl 更好,因为你有一个固定值。
如果您有“else”,请始终选择 nvl。
【讨论】:
如果您将 dual 上的查询替换为任何类型的 有用 查询,则执行时间的差异可以忽略不计。 我们不知道该功能会被使用多少次以及如何使用,它与执行时间有关.. 好吧,这个函数什么都不做,所以我们可以假设它永远不会运行 :) 另一方面,如果我们假设这个 select 做了一些有用的事情,那么性能上的差异就可以忽略不计了。跨度> 【参考方案2】:两个块都输出2
,所以两者都是“等价”。我认为第二种形式更标准,更易于阅读。
比较两个函数:
FUNCTION getSal (p_id NUMBER) RETURN NUMBER
IS
l_return NUMER;
BEGIN
SELECT sal INTO l_return FROM emp WHERE id = p_id;
RETURN l_return;
EXCEPTION
WHEN NO_DATA_FOUND
THEN RETURN 0;
END;
FUNCTION getSal (p_id NUMBER) RETURN NUMBER
IS
l_return NUMER;
BEGIN
SELECT NVL((SELECT sal INTO l_return FROM emp WHERE id = p_id),
0)
INTO l_return
FROM DUAL;
RETURN l_return;
END;
虽然第一行多了几行,但更容易理解的是,如果找不到员工,则返回 0。第二个需要更多时间才能理解,因此会更加混乱。
我肯定会选择第一个,因为它们的性能相同,可读性等于可维护性,因此很重要。
还要注意我的两个块并不完全等价。如果员工的薪水为 NULL,我的第一个查询将返回 NULL,而我的第二个查询将返回 0。
【讨论】:
以上是关于这些片段是等价的吗? (NVL 与例外)的主要内容,如果未能解决你的问题,请参考以下文章
NET问答: 多个 await 和 Task.WaitAll 是等价的吗?
这两种 MySQL 查询形式总是等价的吗?分组依据 + 排序依据 + 限制