繁体   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