这些片段是等价的吗? (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 查询形式总是等价的吗?分组依据 + 排序依据 + 限制

PyQt_PyObject在使用新式信号/插槽时是等价的吗?

lua中的\和\\都是反斜杠吗?是等价的吗?

9.5 等价关系

数字数据类型的 Oracle 等效 NVL