簡體   English   中英

PostgreSQL EXISTS 在用戶定義的 function 中始終返回 true

[英]PostgreSQL EXISTS in user-defined function always returning true

我寫了一個簡單的用戶定義的 function 來檢查是否存在匹配某些條件的行:

CREATE OR REPLACE FUNCTION is_instructor_specialized_in(eid INT, course_area VARCHAR(50))
RETURNS BOOLEAN AS $$
  SELECT EXISTS(SELECT 1 FROM Specializes s WHERE s.eid = eid AND s.name = course_area);
$$ LANGUAGE sql;

我使用以下查詢對其進行了測試:

SELECT is_instructor_specialized_in(2, 'Artificial Intelligence') as function_output, 
    EXISTS(SELECT 1 FROM Specializes s WHERE s.eid = 2 AND s.name = 'Artificial Intelligence') as ground_truth;

並且 function 在應該評估為false時給出了錯誤的true值( Specializes表中沒有這樣的行):圖片

事實上,它總是給出true的值。 我超級困惑。 發生這種情況有什么原因嗎?

版本:x86_64-apple-darwin19.6.0 上的 PostgreSQL 13.2,Apple 編譯 clang 版本 11.0.3 (clang-1103.0.32.62),64 位

就像@wildplasser 暗示的那樣,您的 function 參數eid與表列同名,這絕不是一個好主意。 在這種情況下,它默默地破壞了您的 function。

WHERE s.eid = eid中的不合格eid解析為表列,而不是 function 參數,就像您所期望的那樣。 因此,對於任何非空輸入,此謂詞的計算結果為true 偷偷摸摸的錯誤。

手冊:

如果參數名稱與 function 中的當前 SQL 命令中的任何列名稱相同,則列名稱將優先 要覆蓋它,請使用 function 本身的名稱限定參數名稱,即function_name.argument_name (如果這會與限定的列名沖突,則列名再次獲勝。您可以通過在 SQL 命令中為表選擇不同的別名來避免歧義。)

大膽強調我的。

使用 function 名稱進行資格認證是不得已而為之的尷尬措施。 避免以明確的參數名稱開頭的問題。 一種約定是使用下划線 ( _ ) 為參數添加前綴 - 並且永遠不要對表列做同樣的事情:

CREATE OR REPLACE FUNCTION func_proper(_eid int, _course_area text)
  RETURNS boolean
  LANGUAGE sql STABLE PARALLEL SAFE AS
$func$
SELECT EXISTS(SELECT FROM specializes s WHERE s.eid = _eid AND s.name = _course_area);
$func$;

或者對像你這樣的簡單案例使用位置$n參數引用。 您仍然可以為文檔和命名的 function 調用提供參數名稱:

CREATE OR REPLACE FUNCTION func_proper(_eid int, _course_area text)
  RETURNS boolean
  LANGUAGE sql STABLE PARALLEL SAFE AS
$func$
SELECT EXISTS(SELECT FROM specializes s WHERE s.eid = $1 AND s.name = $2);
$func$;

db<> 在這里擺弄

PL/pgSQL function 中相同命名沖突的默認行為是引發異常,順便說一句。 看:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM