如何使用 INSERT ... ON DUPLICATE KEY UPDATE 解决 PostgreSQL PL/pgSQL 函数中的“不明确的列引用”错误?

问题描述 投票:0回答:1

我正在开发一个 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;
postgresql
1个回答
0
投票

在函数

function create_email_verification
之间存在冲突

  • email
     中的
    列名称
    email_verifications
  • 输出结果表(返回TABLE(... email text...)

您可以使用 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;
$$;
© www.soinside.com 2019 - 2024. All rights reserved.