我正在开发一个 PostgreSQL PL/pgSQL 函数,该函数将记录插入表中或使用 ON CONFLICT 更新记录。但是,当我运行该函数时,遇到以下错误:
[42702] ERROR: column reference "email" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column.
Where: PL/pgSQL function create_email_verification(text, text, timestamp with time zone) line 3 at RETURN QUERY
表结构:
CREATE TABLE email_verifications
(
id INTEGER DEFAULT nextval('email_verifications_id_seq'::regclass) NOT NULL PRIMARY KEY,
email TEXT NOT NULL CONSTRAINT unique_email UNIQUE,
code TEXT NOT NULL,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
verified_at TIMESTAMP WITH TIME ZONE
);
功能:
create function create_email_verification(
p_email text,
p_code text,
p_expires_at timestamp with time zone)
returns TABLE(
id integer,
email text,
code text,
expires_at timestamp with time zone,
created_at timestamp with time zone
) language plpgsql
as
$$
BEGIN
RETURN QUERY
INSERT INTO email_verifications (email, code, expires_at)
VALUES (p_email, p_code, p_expires_at)
ON CONFLICT (email)
DO UPDATE
SET
code = EXCLUDED.code,
expires_at = EXCLUDED.expires_at
RETURNING
email_verifications.id,
email_verifications.email,
email_verifications.code,
email_verifications.expires_at,
email_verifications.created_at;
END;
$$;
奖金信息:
在函数外部运行相同的查询效果非常好。例如,以下查询执行没有问题:
INSERT INTO email_verifications (email, code, expires_at)
VALUES ('[email protected]', '123456', NOW())
ON CONFLICT (email)
DO UPDATE
SET
code = EXCLUDED.code,
expires_at = EXCLUDED.expires_at
RETURNING id, email, code, expires_at, created_at;
在函数
function create_email_verification
之间存在冲突
email
中的列名称
email_verifications
和您可以使用 ON CONFLICT ON CONSTRAINT 形式编写 ON CONFLICT 子句
ON CONFLICT ON CONSTRAINT unique_email
使用来自
email TEXT NOT NULL CONSTRAINT unique_email UNIQUE
的约束名称
从而解决名称上的冲突。
或者,如果可能的话,您可以更改返回表中的列名称
returns TABLE(
...
email_x text,
...
)
尝试
create function create_email_verification(
p_email text,
p_code text,
p_expires_at timestamp with time zone)
returns TABLE(
id integer,
email text,
code text,
expires_at timestamp with time zone,
created_at timestamp with time zone
) language plpgsql
as
$$
BEGIN
RETURN QUERY
INSERT INTO email_verifications (email, code, expires_at)
VALUES (p_email, p_code, p_expires_at)
ON CONFLICT ON CONSTRAINT unique_email
DO UPDATE
SET
code = EXCLUDED.code,
expires_at = EXCLUDED.expires_at
RETURNING
email_verifications.id,
email_verifications.email,
email_verifications.code,
email_verifications.expires_at,
email_verifications.created_at;
END;
$$;