SQL CONCAT

Joins two or more text values together into one — and unlike the || operator, safely treats NULL as an empty string instead of contaminating the whole result.

What & Why

CONCAT(a, b, c, ...) joins any number of values into a single string, converting non-text values (like numbers) automatically. Its standout behavior: if any input is NULL, CONCAT simply treats it as an empty string and keeps going — it doesn't propagate NULL the way most functions do.

See How It Works

BUSINESS QUESTION

Product wants to compare CONCAT with || while building feature labels from the nullable deprecated_at column.

idnamedescriptionteamreleased_atdeprecated_at
1Activation ChecklistGuides new users through setupgrowth2024-01-20NULL
2CSV ExportExports report dataplatform2024-02-14NULL
3Invite NudgesPrompts workspace collaborationgrowth2024-03-05NULL
4Legacy DashboardOriginal reporting surfaceanalytics2023-08-102024-06-01
Watch CONCAT and || handle the same nullable value differentlyExample 1 of 4
CONCAT(name, ' · ', deprecated_at::text) vs name || ' · ' || deprecated_at::text
idnamedeprecated_atconcat_labeloperator_label
1Activation ChecklistNULLActivation Checklist · NULL
2CSV ExportNULL??
3Invite NudgesNULL??
4Legacy Dashboard2024-06-01??

CONCAT treats the missing date as empty text, while || propagates NULL.

EXAMPLE QUERY
SELECT
  id,
  name,
  deprecated_at,
  CONCAT(name, ' · ', deprecated_at::text) AS concat_label,
  name || ' · ' || deprecated_at::text AS operator_label
FROM product.features
ORDER BY id;
Now You Try

Practice this concept

Product compares CONCAT with || while building feature labels from nullable deprecated_at.

Available schema
product

Prefix tables with product.table_name.

idnamedeprecated_atconcat_labeloperator_label
product.features
ColumnType
idinteger
nametext
descriptiontext
teamtext
released_attimestamp with time zone
deprecated_attimestamp with time zone
internal_priorityinteger
query.sql
Intermediate business practice

Sign up free to try it on a real business scenario