- SQLSTATE
- 42702
- Condition name
ambiguous_column- Product
- PostgreSQL
- Versions
- PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
- Category
- Syntax & Names
- Last reviewed
- 24 October 2026
On this page
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; 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'; 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-onlyGive 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-onlyUSING (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 schemaQualify 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;
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);
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;
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
- PostgreSQL error codes (Appendix A)
- Table expressions: joins, USING and aliases
- PL/pgSQL variable substitution
- Query language (SQL) functions: argument names
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.