错误:列“xxx”不存在:Postgresql plpgsql存储过程

3

我写了一个简单的PG SP作为概念证明。然而,当我运行SP时,我收到了一个错误信息。这是模式和SP的SQL:

CREATE TABLE foobar
(
    forename    VARCHAR(255),
    surname     VARCHAR(32),
    enrolement_ts   TIMESTAMP,
    age     SMALLINT,
    major       VARCHAR(32),
    user_id     INTEGER
);


CREATE OR REPLACE FUNCTION insert_foobar (
       forename         VARCHAR(255),
       surname          VARCHAR(32),
       age      SMALLINT,
       major        VARCHAR(32) ) RETURNS VOID AS $$
    INSERT INTO foobar VALUES (forename, surname, getdate(), age, major, user_id());
$$ LANGUAGE sql;

当我在命令行输入函数定义时,我收到以下错误提示:
ERROR:  column "forename" does not exist
LINE 6:     INSERT INTO foobar VALUES (forename, surname,...
                                           ^

有人能找出/解释导致此错误的原因吗?显然,列名forename在表结构中存在,所以我不理解错误消息。


顺便提一下,Postgres没有“存储过程”,只有“函数”。这可能看起来是一个吹毛求疵的评论,但关键的区别在于,函数只能返回某些东西,而不能像其他一些DBMS中的存储过程那样将其作为结果集输出。 - IMSoP
有趣的是,在Postgres 9.2下,它似乎按预期工作,如此SQLFiddle演示所示,因此无论发生了什么事情,都被认为是一个错误并在某个时候得到修复。 - IMSoP
1个回答

6
在PostgreSQL 9.2之前,使用纯SQL编写的函数参数(而不是诸如pl/pgSQL之类的过程性语言)不能通过它们的名称来引用命名参数,即使函数签名可以包含它们(“用于文档目的”)。 当前SQL函数手册页面包括以下说明:
请注意:从PostgreSQL 9.2开始,添加了使用名称引用SQL函数参数的功能。要在旧服务器中使用的函数必须使用$ n符号。
因此,为了与9.2之前的版本一起使用,您的函数需要像这样:
CREATE OR REPLACE FUNCTION insert_foobar (
       forename         VARCHAR(255),
       surname          VARCHAR(32),
       age      SMALLINT,
       major        VARCHAR(32) ) RETURNS VOID AS $$
    INSERT INTO foobar VALUES ($1, $2, getdate(), $3, $4, user_id());
$$ LANGUAGE sql;

(我假设getdate()user_id()是本地定义的函数,包装了now()和所需的用户ID逻辑。)

+1 是因为仔细解释了错误发生的原因。如果只依靠生成的错误消息,我永远不会想到这个。 - Homunculus Reticulli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接