Tier 3 · Intermediate

String Concatenation and Formatting in SQL

By Owen Middleton · Updated September 2026 · Examples run on PostgreSQL 17

What is String Concatenation in SQL?

PostgreSQL has three ways to join strings together — the || operator, the CONCAT family, and FORMAT — and the choice between them matters whenever a column might be NULL.

You're building a display label for each customer: their name and country, formatted for a report. Some customers are missing a country. Whether the result is NULL, partial, or gracefully filled depends entirely on which tool you use.

What does the || operator do in PostgreSQL?

|| is the simplest: it concatenates two values with a binary operator. But it follows the standard NULL propagation rule — if either side is NULL, the result is NULL. A missing country means the entire label comes back NULL:

SELECT
  name || ' (' || country || ')' AS customer_label
FROM customers
LIMIT 5

If country is NULL for any customer, that row returns NULL for customer_label. No error — just a missing value where you expected a string.

How does CONCAT handle NULL values?

CONCAT fixes this. It accepts any number of arguments and treats NULL inputs as empty strings:

SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM customers

If last_name is NULL, CONCAT skips it and returns just the first name. This is usually what you want when building display values from optional fields.

How do you join strings with a separator in SQL?

CONCAT_WS (concatenate with separator) takes a separator as its first argument and joins all non-NULL values with that separator between them — no doubled separators, no trailing delimiter:

SELECT CONCAT_WS(', ', last_name, first_name, middle_name) AS full_name
FROM customers

If middle_name is NULL, the output is 'Smith, John' — not 'Smith, John, '. The separator only appears between values that actually exist.

How do you build a string from a template with FORMAT?

FORMAT works from a template. You write a string with %s placeholders and provide the values to fill them in order:

SELECT FORMAT('Order #%s placed on %s', id, ordered_at::date) AS order_label
FROM orders

FORMAT coerces each argument to text automatically, so you don't need to cast numbers or dates first. NULL arguments are inserted as empty strings. FORMAT is especially useful when building a label with fixed structure — if you find yourself writing long || chains with multiple casts and literal strings, FORMAT is usually cleaner.

One practical difference: CONCAT_WS with a separator handles variable-length data (unknown number of non-NULL fields) cleanly. FORMAT is better when the output has fixed structure with a known set of placeholders.

Why does concatenating with || return NULL?

The one thing that trips people up: || with NULL produces NULL, not a partial string.

If you're building a label from multiple columns and any might be NULL, use CONCAT or CONCAT_WS instead of ||. The || operator is the right choice when you know the inputs are not NULL, or when you want NULL to propagate intentionally — for example, when a NULL in one field means the entire record is incomplete and the label should be absent.

Practice String Concatenation in SQL

Practice · easy ecommerce · Brightlane

Brightlane's reporting system builds order reference strings by combining a prefix and an order identifier.

Write a query to return the result of concatenating 'ORDER-' and '1042' with the || operator.

Output:

  • A single row with one column, order_ref, containing the concatenated string.
Schema · ecommerce5 tables? = nullable
categories
idinteger
nametext
parent_id?integer
products
idinteger
nametext
category_id?integer
pricenumeric
stock_qtyinteger
attributes?jsonb
order_items
idinteger
order_id?integer
product_id?integer
quantityinteger
unit_pricenumeric
customers
idinteger
nametext
emailtext
city?text
countrytext
created_attimestamptz
is_activeboolean
orders
idinteger
customer_id?integer
ordered_attimestamptz
statustext
total_amountnumeric

Run previews · Check grades

Write a query, then run it to see results here.

Worked solution

The full breakdown walks through the shape, each clause, why this approach beats the alternatives, and the trap to avoid.

See the full worked solution

9 String Concatenation practice problems

Start learning to practice all 9 String Concatenation problems, with instant grading and mastery tracking.

Deeper guides on String Concatenation

Common questions about String Concatenation

Can you concatenate two numbers with the double pipe operator?

Not on their own. Two integers side by side raise an operator does not exist error, because the operator needs at least one text operand to know what you meant. Cast one of them to text and it works.

Does CONCAT ever return NULL?

No. It treats NULL arguments as empty strings, so concatenating nothing but NULLs gives an empty string rather than NULL. That is the behaviour that makes it the safer choice for building a label from optional fields.

What does FORMAT do with a NULL argument?

It inserts an empty string and carries on, rather than making the whole result NULL. Combined with automatic conversion of numbers and dates to text, that makes FORMAT the tidiest option when the output has a fixed shape and some fields may be missing.

How you actually get good at SQL

Reading explains SQL. Writing it, over and over with instant feedback, is what makes you fluent.

That's the whole SQLMaxx loop: 600+ real problems, instant AI feedback, mastery you can actually see, and spaced review that won't let you forget.

A stack of SQL practice problem cards, the top card showing an employees table.
615 problems · 66 concepts

Real problems. Not toy examples.

615 hand-built problems spanning all 66 concepts, from basic SELECTs to window functions, built on real schemas and real business questions, the kind you'll actually get asked on the job. Enough reps to make SQL automatic.

A retro computer showing a SQL query marked correct with a green checkmark.
Instant AI feedback

Write a query. Know if it's right in one second.

No copying an answer and hoping it clicked. The AI grader checks your real query against real data, catches exactly what's wrong, and explains the fix in plain English, like a senior analyst reading over your shoulder on every problem.

A circular mastery progress dial filling from blue to green, the SQLMaxx diamond at its center.
Mastery tracking

Stop guessing whether you actually know it.

SQLMaxx tracks every concept and shows you what you've mastered and what's still shaky. Your skills fill in one concept at a time, so 'I think I get joins' becomes something you can prove.

A SQL query editor circled by a blue return arrow with a clock, scheduled to come back for review.
Spaced review

Learn it once. Keep it for good.

Most of what you learn this week fades by next week. So when a concept comes due for review, SQLMaxx hands you a fresh problem to solve from a blank editor, not a flashcard to re-read. A research-backed spaced-repetition algorithm (FSRS) times each return for right before you'd forget, so your SQL is still there months later, when the interview or the job actually needs it.