模棱两可的函数参数

Posted

技术标签:

【中文标题】模棱两可的函数参数【英文标题】:Ambiguous function arguments 【发布时间】:2015-11-17 02:18:53 【问题描述】:

示例函数:

CREATE OR REPLACE FUNCTION update_a_table(id int, name text)
RETURNS void AS $$
BEGIN
    UPDATE a_table 
    SET name = name
    WHERE id = id;
END;
$$ LANGUAGE plpgsql;

导致此错误:

ERROR:  column reference "name" is ambiguous
LINE 2:   SET name = name
                     ^
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.

很明显,我可以通过更改参数名称来纠正这个问题。有没有替代方案?

【问题讨论】:

更改参数的名称是解决此问题的唯一明智方法。 【参考方案1】:

通常,在编程中为两个不同的对象使用相同的名称是一种不好的做法。您不应该这样做,更改参数名称是最好的解决方案。然而,Postgres 敞开大门(为了与旧版本兼容)。你可以设置configuration parameter:

set plpgsql.variable_conflict to use_variable;

参数的可能值:error(默认)、use_variableuse_column

也可以只为给定函数设置参数:

CREATE OR REPLACE FUNCTION update_a_table(id int, name text)
RETURNS void AS $$
#variable_conflict use_variable
BEGIN
    UPDATE a_table 
    SET name = name
    WHERE id = id;
END;
$$ LANGUAGE plpgsql;

或者,您可以明确限定不明确的名称,这是比上述解决方案更好的解决方案。限定名称的形状为<function_name>.<parameter_name>,例如update_a_table.id

CREATE OR REPLACE FUNCTION update_a_table(id int, name text)
RETURNS void AS $$
BEGIN
    UPDATE a_table 
    SET name = update_a_table.name
    WHERE a_table.id = update_a_table.id;
END;
$$ LANGUAGE plpgsql;

【讨论】:

我很抱歉,但禁用 variable_conflict 不是一个好主意(不是没有强烈警告)。解决方案应该始终使用限定名称。 @PavelStehule - 谢谢,我已经添加了两个词。 第二种解决方案对我不起作用。错误:缺少表“update_a_table”的 FROM 子句条目 @DominikK - 使用示例数据和您的查询提出问题。您可以使用SqlFiddle 来显示问题。 @EleanorHolley - 这是一个误解。限定名称中没有<schema_name>,您应该改用<function_name>。查看更新后的答案。【参考方案2】:

对于极难检测到的错误,此错误更安全。 PLpgSQL 好的风格需要

    在任何嵌入式 SQL 中随处使用限定名称 - 访问函数参数时使用模式 function_name.parameter_name

    以前的 Postgres 版本没有这种检测,只有一种保护是使用带有特殊前缀的变量。通常使用'_'作为前缀。规则很简单 - 当您的函数包含嵌入式 SQL 时,所有变量和参数名称都应以“_”开头。这样可以更安全地防止名称冲突并提高可读性,因为您可以快速了解什么是变量以及什么是 SQL 标识符。

【讨论】:

恐怕不太明白。我在哪里可以找到有关特殊前缀的信息?什么是嵌入式 SQL? 前缀 '_' 并不特殊 - 它通常用于 - postgres.cz/wiki/PL/… 。许多建议与 Oracle 的 PL/SQL 共享。嵌入式 SQL 是在 PLpgSQL 中用作第一类对象(语言的组成部分)的任何 SQL 语句。【参考方案3】:
CREATE OR REPLACE FUNCTION update_a_table_1(int,text)
RETURNS void AS $$
BEGIN
    UPDATE a_table 
    SET name = $2
    WHERE id =$1;
END;
$$ LANGUAGE plpgsql;

您可以在您的 如果你有 2 个 args,所以你只需要通过提供它来访问它们 索引($1$2)但是当你有很多时,IMO 这不是一个好主意 要传递的参数(例如一个具有 10 或 10+ 个参数的函数,它可能 把你弄糊涂了)

【讨论】:

以上是关于模棱两可的函数参数的主要内容,如果未能解决你的问题,请参考以下文章

显式引用一个参数

Python 检查模块:仅关键字参数

数组②Array 构造函数

使用模板参数模板解决模棱两可调用的 C++ 默认行为是啥?

如何处理模棱两可的模板参数?

url为什么要编码