Skip to content
PostgreSQL

PostgreSQL Error 42702

column reference is ambiguous

Applies to: PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
Last technically reviewed 24 October 2026 on PostgreSQL 18.6 (PGlite 0.5.11)
The full message
ERROR:  column reference "dept_id" is ambiguous
Other forms of this message
In PL/pgSQL: a variable, parameter or OUT column with the same name as a table column
ERROR:  column reference "emp_id" is ambiguous
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.
CONTEXT:  PL/pgSQL function get_emp(integer) line 3 at RETURN QUERY
ORDER BY a name shared by two output columns
ERROR:  ORDER BY "name" is ambiguous
How psql adds the position (reconstructed from the error position the server reports)
LINE 1: SELECT dept_id FROM emp JOIN dept ON emp.dept_id = dept.dept_id;
               ^
SQLSTATE
42702
Condition name
ambiguous_column
Product
PostgreSQL
Versions
PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
Last reviewed
24 October 2026

What it means

SQLSTATE 42702 means an unqualified column name matches columns in more than one table of the query, or, inside a PL/pgSQL function, matches both a variable and a table column, so PostgreSQL will not guess which one you meant.

When a query joins tables that share a column name, such as dept_id or name in both emp and dept, an unqualified reference to it could mean either table. PostgreSQL refuses to choose and raises 42702 (ambiguous_column). The message names the column but not the tables; check which tables in FROM have it. The fix is to qualify the column with its table or alias (e.dept_id). A join written with USING (dept_id) merges the two columns into one, so unqualified dept_id is then allowed; columns not listed in USING stay ambiguous. ORDER BY has its own form, "ORDER BY "name" is ambiguous", when two output columns have the same name.

In PL/pgSQL functions the error has a DETAIL line: It could refer to either a PL/pgSQL variable or a table column. Parameters, declared variables and the output columns of RETURNS TABLE are all variables, so RETURNS TABLE (emp_id int, ...) followed by SELECT emp_id FROM emp is ambiguous. CONTEXT names the function and line. LANGUAGE sql functions behave differently: there the column silently wins over a parameter of the same name, which raises no error but can return wrong results.

Common causes

  • A join of two tables that share a column name (id, name, dept_id, created_at), with the column written unqualified in SELECT, WHERE, ON, GROUP BY or ORDER BY.
  • A join condition such as ON dept_id = dept_id, which is ambiguous on both sides.
  • A query that used to read one table and then gained a JOIN, so names that were unique are not any more.
  • A PL/pgSQL parameter or variable named like a column (dept_id), especially the output columns of RETURNS TABLE, used inside a query.
  • Two output columns with the same name (e.name and d.name) and an ORDER BY name.

Diagnose it

Read-only These queries only read the system catalogs (pg_catalog, information_schema) and statistics views such as pg_stat_activity and pg_locks. They do not change data, roles or settings, so they are safe to run first.

Which tables in the query have the column?

SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'public'
  AND table_name IN ('emp', 'dept')   -- the tables in your FROM clause
  AND column_name = 'dept_id'          -- the name from the message
ORDER BY table_name;
What to look for

More than one row confirms the clash and tells you which tables to choose from. Qualify the reference with the alias of the table you mean.

Show a function's parameters and output columns

For the PL/pgSQL form, compare the function's argument and result names with the columns its queries use.

SELECT proname,
       pg_get_function_arguments(oid) AS arguments,
       pg_get_function_result(oid)    AS result
FROM pg_proc
WHERE proname = 'get_emp';
What to look for

For example p int and TABLE(emp_id integer, name text): emp_id and name are variables inside the function, so any unqualified emp_id or name in its queries is ambiguous.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Qualify every column with a table alias

Read-only

Give each table a short alias and prefix every column with it. This removes the ambiguity and keeps the query working when someone later adds a column with the same name to another table.

SELECT e.emp_id, e.name AS emp_name, d.name AS dept_name
FROM emp AS e
JOIN dept AS d ON d.dept_id = e.dept_id
ORDER BY emp_name;

Join with USING when the key has the same name in both tables

Read-only

USING (dept_id) joins on equal dept_id values and outputs a single dept_id column, which may then be written unqualified. Avoid NATURAL JOIN as a shortcut: it joins on every column with a matching name, so with emp and dept it would also require emp.name = dept.name and silently return the wrong rows.

SELECT dept_id, e.name
FROM emp AS e
JOIN dept AS d USING (dept_id);

In PL/pgSQL, qualify the columns or rename the variables

Changes schema

Qualify table columns with an alias inside the function (e.emp_id), and give parameters and variables names that cannot clash, for example a p_ prefix. The output columns of RETURNS TABLE are part of the function's signature, so renaming them changes what callers see; qualifying the table columns avoids that. PL/pgSQL also offers #variable_conflict use_column or use_variable at the top of the function body, but explicit qualification is clearer.

Caution: CREATE OR REPLACE FUNCTION keeps the existing parameter names: renaming p to p_dept_id this way fails with "cannot change name of input parameter" (SQLSTATE 42P13). Renaming needs DROP FUNCTION and CREATE FUNCTION, which removes privileges granted on the function and fails if other objects depend on it, so plan it as a migration.

CREATE OR REPLACE FUNCTION get_emp(p int)
RETURNS TABLE (emp_id int, name text)
LANGUAGE plpgsql AS $$
BEGIN
    RETURN QUERY
    SELECT e.emp_id, e.name
    FROM emp AS e
    WHERE e.dept_id = p;
END
$$;

Examples

Selecting a column that both joined tables have

CREATE TABLE emp (emp_id int, name text, dept_id int);
CREATE TABLE dept (dept_id int, name text);

SELECT dept_id, emp_id
FROM emp
JOIN dept ON emp.dept_id = dept.dept_id;
Result
ERROR:  column reference "dept_id" is ambiguous

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

An OUT column of RETURNS TABLE clashing with a table column

CREATE FUNCTION succeeds: PL/pgSQL checks the query only when the function first runs it. The fix is to write SELECT e.emp_id, e.name FROM emp AS e WHERE e.dept_id = p.

CREATE TABLE emp (emp_id int, name text, dept_id int);

CREATE FUNCTION get_emp(p int)
RETURNS TABLE (emp_id int, name text)
LANGUAGE plpgsql AS $$
BEGIN
    RETURN QUERY SELECT emp_id, name FROM emp WHERE dept_id = p;
END
$$;

SELECT * FROM get_emp(1);
Result
ERROR:  column reference "emp_id" is ambiguous
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.
CONTEXT:  PL/pgSQL function get_emp(integer) line 3 at RETURN QUERY

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

ORDER BY a name two output columns share

Both output columns are called name. Give them different aliases (emp_name, dept_name) or order by e.name.

CREATE TABLE emp (emp_id int, name text, dept_id int);
CREATE TABLE dept (dept_id int, name text);

SELECT e.name, d.name
FROM emp AS e
JOIN dept AS d USING (dept_id)
ORDER BY name;
Result
ERROR:  ORDER BY "name" is ambiguous

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

How to prevent it

In any query with more than one table, alias every table and qualify every column, including in ON, WHERE, GROUP BY and ORDER BY. Give output columns distinct names when two tables share a column such as name.

In PL/pgSQL, use a naming convention for parameters and variables (p_ and v_ prefixes) and always alias tables in function queries. Remember that LANGUAGE sql functions give no error for the same clash (the column wins), so the convention matters there too.

Common questions

How do I fix "column reference is ambiguous" in PostgreSQL?

Prefix the column with the table or alias you mean, for example e.dept_id instead of dept_id. Find which tables in FROM have the column with the first diagnostic query.

Why does a PL/pgSQL function say the column could refer to a variable?

A parameter, declared variable or RETURNS TABLE output column has the same name as a table column used in a query inside the function. Qualify the table column with an alias, or rename the variable.

Why is the column not ambiguous when I join with USING?

USING (col) merges the two join columns into one output column, so an unqualified reference to it is unambiguous. Other columns that both tables share are still ambiguous.

Does a LANGUAGE sql function raise this error too?

No. In SQL functions a column name takes precedence over a parameter with the same name, so WHERE dept_id = dept_id compares the column with itself and matches every row with a non-null dept_id. Qualify the parameter with the function name (get_count.dept_id), qualify the column with the table, or choose a different parameter name.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on PostgreSQL 18.6 (PGlite 0.5.11). SQL-level examples were run in PGlite (PostgreSQL compiled to WebAssembly); examples that need a running server are shown as documented in the PostgreSQL documentation.

Still stuck on a PostgreSQL error?

Browse the full PostgreSQL error library, or get hands-on help from an experienced SQL professional.