它可以引用 PL/pgSQL 变量或表列
Posted
技术标签:
【中文标题】它可以引用 PL/pgSQL 变量或表列【英文标题】:It could refer to either a PL/pgSQL variable or a table column 【发布时间】:2014-03-06 21:41:52 【问题描述】:我在 pgsql 中有一个函数
CREATE OR REPLACE FUNCTION core.date_bs_from_ad(date_in_ad date)
RETURNS character varying AS
$$
BEGIN
RETURN(
SELECT date_in_bs FROM core.date_conversion
WHERE date_in_ad = $1
);
END
$$
LANGUAGE plpgsql;
它的创建没有错误,但是当我使用此功能时出现以下错误:
ERROR: column reference "date_in_ad" is ambiguous
LINE 3: WHERE date_in_ad = $1
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: SELECT (
SELECT MAX(date_in_bs) FROM core.date_conversion
WHERE date_in_ad = $1
)
CONTEXT: PL/pgSQL function core.date_bs_from_ad(date) line 3 at RETURN
********** Error **********
ERROR: column reference "date_in_ad" is ambiguous
SQL state: 42702
Detail: It could refer to either a PL/pgSQL variable or a table column.
Context: PL/pgSQL function core.date_bs_from_ad(date) line 3 at RETURN
【问题讨论】:
错误信息说明了一切:你有一个列和一个同名的参数。您需要更改参数的名称以避免歧义 @a_horse_with_no_name,您的评论应该是答案而不是评论。请将其发布为答案。 【参考方案1】:在这种情况下,代码足够简单直接,有时在函数文本的开头依赖这些特殊的 plpgsql 命令之一很有用:
#variable_conflict error
#variable_conflict use_variable
#variable_conflict use_column
在这种情况下,它将按如下方式使用:
CREATE OR REPLACE FUNCTION core.date_bs_from_ad(date_in_ad date)
RETURNS character varying AS
$$
#variable_conflict use_column
BEGIN
RETURN(
SELECT date_in_bs FROM core.date_conversion
WHERE date_in_ad = $1
);
END
$$
这对于不与参数冲突而是与输出列名称冲突的情况特别有用,例如:
CREATE OR REPLACE FUNCTION core.date_bs_from_ad(p_date_in_ad date)
RETURNS TABLE (date_in_bs character varying) AS
$$
BEGIN
RETURN QUERY
SELECT date_in_bs FROM core.date_conversion
WHERE date_in_ad = p_date_in_ad;
END;
$$
上面的函数将失败,因为编译器无法确定date_in_bs
是输出变量名称还是core.date_conversion
的列之一。对于此类问题,#variable_conflict use_column
命令确实可以提供帮助。
【讨论】:
【参考方案2】:SQL 标识符和 PlpgSQL 变量之间存在冲突。没有干净的,你想要什么。你写了一个谓词,它总是正确的。
很好用:
局部变量的前缀(通常是“_”) 嵌入式 SQL 中的限定名称 - 如 table_name.column_name所以两种技术(只需要一种)
CREATE OR REPLACE FUNCTION core.date_bs_from_ad(_date_in_ad date)
RETURNS character varying AS $$
BEGIN
RETURN SELECT dc.date_in_bs
FROM core.date_conversion dc
WHERE dc.date_in_ad = _date_in_ad;
END
$$ LANGUAGE plpgsql;
对于这些一行函数,SQL语言比较好:
CREATE OR REPLACE FUNCTION core.date_bs_from_ad(_date_in_ad date)
RETURNS character varying AS $$
SELECT dc.date_in_bs
FROM core.date_conversion dc
WHERE dc.date_in_ad = $1;
$$ LANGUAGE sql;
【讨论】:
我自己不是_
前缀的忠实粉丝——这有点难以注意到,并且在阅读大量代码时可能会造成混淆。我更喜欢更显眼的前缀,比如p_
。 (无论如何,答案当然是正确的)。
匈牙利公约在这里没有意义。但是好的命名很重要。 PK 和 FK 的智能命名可以简化书写和阅读查询。以上是关于它可以引用 PL/pgSQL 变量或表列的主要内容,如果未能解决你的问题,请参考以下文章
从 PL/PGSQL 引用会话变量 (\set var='value')