NVL 與 COALESCE 鮮爲人知的區別

你們都知道的區別:函數

NVL Oracle 專屬 只支持兩個參數
COALESCE SQL 標準 支持多個參數

可是今天偶然間還發現一個重要差異:濫用 NVL 可能致使額外的計算spa

NVL 不管前面的參數是否爲 NULL 均會計算全部參數
COALESCE 若是遇到一個不爲 NULL 的參數,則不計算後面的

以 PL/SQL 爲例,NVL 的表現就如同通常的函數,但 COALESCE 更像是一個語句,能夠成功避免進行耗時的運算;ci

SQL 中可能也是如此,歡迎讀者自行驗證並在評論區討論!it

DECLARE
  l_n VARCHAR2(4000) := 'x';
  l_s VARCHAR2(4000) := 'x';
  FUNCTION Expensive_Function RETURN VARCHAR2 IS
  BEGIN
    Dbms_Output.Put_Line('Expensive_Function !!!');
    RETURN 'x';
  END Expensive_Function;
  FUNCTION Common_Function(p_S1 IN VARCHAR2, p_S2 IN VARCHAR2)
    RETURN VARCHAR2 IS
  BEGIN
    RETURN 'x';
  END Common_Function;
  PROCEDURE Common_Procedure(p_S1 IN VARCHAR2, p_S2 IN VARCHAR2) IS
  BEGIN
    RETURN;
  END Common_Procedure;
BEGIN
  Dbms_Output.Put_Line('Function');
  l_s := Common_Function(l_n, Expensive_Function);
  Dbms_Output.Put_Line('Procedure');
  Common_Procedure(l_n, Expensive_Function);
  Dbms_Output.Put_Line('Nvl');
  l_s := Nvl(l_n, Expensive_Function); -- Nvl就像普通的函數同樣,要先計算參數
  Dbms_Output.Put_Line('Coalesce');
  l_s := Coalesce(l_n, Expensive_Function); -- 很是特殊的函數,行爲相似於 IF-ELSE CASE AND OR 不會進行多餘的計算
  Dbms_Output.Put_Line('CASE');
  l_s := CASE l_s
           WHEN 'x' THEN
            'xxx'
           WHEN Expensive_Function THEN
            'yyy'
           ELSE
            Expensive_Function
         END;
  Dbms_Output.Put_Line('AND');
  IF NOT (l_n IS NULL AND Expensive_Function IS NULL) THEN
    NULL;
  END IF;
  Dbms_Output.Put_Line('OR');
  IF l_n IS NOT NULL OR Expensive_Function IS NOT NULL THEN
    NULL;
  END IF;
END;io

相關文章
相關標籤/搜索