I’m working on a PostgreSQL PL/pgSQL function that inserts a record into a table or updates it using ON CONFLICT. However, when I run the function, I encounter the following error:
<code>[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
</code>
<code>[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
</code>
[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
Table structure:
<code>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
);
</code>
<code>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
);
</code>
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
);
Function:
<code>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;
$$;
</code>
<code>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;
$$;
</code>
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;
$$;
Bonus information :
Running the same query outside the function works perfectly fine. For example, the following query executes without issues:
<code>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;
</code>
<code>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;
</code>
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;