SQLNATURAL JOIN & USING

NATURAL JOIN & USING

Writing out ON c.customer_id = o.customer_id gets repetitive when the join column has the exact same name in both tables, which happens constantly with well-designed foreign keys. SQL offers two shorthands for this specific situation: the USING clause, and the more aggressive NATURAL JOIN. Both can save typing, but only one of them is generally considered safe to use in production code.

USING: shorthand for an identical column name

When the join column has the same name in both tables — customer_id in both customers and orders, for instance — USING lets you name that column once instead of repeating table_a.column = table_b.column.

ON vs USING — identical results

SQL
-- Standard ON syntax
SELECT c.name, o.order_id, o.amount
FROM customers c
JOIN orders o
  ON c.customer_id = o.customer_id;

-- Equivalent, using USING
SELECT c.name, o.order_id, o.amount
FROM customers c
JOIN orders o
  USING (customer_id);

Both queries return the identical result set. USING also has one small extra benefit over ON: the shared column (customer_id) appears only once in the output instead of twice, and it can be referenced unqualified (just customer_id, without a table prefix) in the SELECT list or WHERE clause, since there is no longer any ambiguity about which one you mean.

NATURAL JOIN: automatic, implicit matching

NATURAL JOIN goes a step further than USING: instead of naming the shared column yourself, it automatically joins on every column that has an identical name in both tables, with no ON or USING clause at all.

NATURAL JOIN — no explicit join column

SQL
SELECT name, order_id, amount
FROM customers
NATURAL JOIN orders;
name   | order_id | amount
-------+----------+-------
Alice  | 101      | 250.00
Alice  | 102      | 75.50
Bob    | 103      | 300.00
Carol  | 104      | 120.00

Here, customer_id happens to be the only column shared between customers and orders, so NATURAL JOIN produces the same result as the ON/USING versions above. That word "happens" is exactly the problem.

NATURAL JOIN is fragile — avoid it in production
NATURAL JOIN's matching columns are determined implicitly by whatever columns happen to share a name at query time, not by an explicit condition you control. If someone later adds a new column called, say, created_by to both customers and orders — completely unrelated to the original join logic — NATURAL JOIN will silently start joining on created_by too, changing the query's behavior without a single line of the query itself being edited. This kind of silent, schema-driven behavior change is exactly what makes NATURAL JOIN dangerous in real systems, which is why most SQL style guides recommend avoiding it entirely and always being explicit with ON (or USING, when the column names genuinely match and are unlikely to accumulate new shared names).
Choosing between ON, USING, and NATURAL JOIN

In practice, ON is the safest default because the join condition is always fully explicit and immune to future schema changes. USING is a reasonable, low-risk shorthand when the column names genuinely match and you want slightly less repetition. NATURAL JOIN should generally be avoided outside of quick, throwaway queries against a schema you fully control and are not going to change.

  • USING (column) is shorthand for ON a.column = b.column when the column name matches in both tables.

  • NATURAL JOIN automatically joins on every identically-named column, with no explicit condition at all.

  • NATURAL JOIN's behavior can silently change if the schema later gains a new shared column name.

  • Most style guides recommend explicit ON clauses in production code, treating NATURAL JOIN as unsafe.