Concatenate two or more strings into a single string. Behavior with NULL values differs significantly between engines.

Joins two or more strings together. Syntax varies: MySQL uses CONCAT(), PostgreSQL/SQLite use double-pipe, SQL Server uses plus or CONCAT(). Watch for implicit type conversion and NULL propagation -- CONCAT(NULL, x) returns NULL in most engines.

Compatibility

Filter by Database
SQL CONCAT Compatibility Across Databases
Database System Support Status Since Version Notes
MySQL Native all CONCAT() ignores NULL arguments (treats them as empty string). CONCAT_WS(sep, ...) skips NULLs and adds a separator between non-null values.
PostgreSQL Native all CONCAT() ignores NULLs (like MySQL). The || operator is the standard alternative but propagates NULLs — 'a' || NULL = NULL. Use CONCAT() or COALESCE() when NULL safety matters.
SQL Server Native 2012 CONCAT() added in SQL Server 2012 and treats NULLs as empty strings. Before 2012, use + operator — but + propagates NULLs unless SET CONCAT_NULL_YIELDS_NULL OFF. CONCAT_WS() added in SQL Server 2017.
Oracle Native all CONCAT() accepts exactly two arguments. For more than two strings, use the || operator or nest CONCAT() calls. In Oracle, NULL is treated as empty string in string concatenation (|| propagates, but CONCAT ignores).
SQLite Native 3.44.0 CONCAT() added in SQLite 3.44.0 (Nov 2023). Before that, use the || operator exclusively. || propagates NULLs — use COALESCE() to guard against them.

Details

The biggest gotcha: the || operator propagates NULLs in PostgreSQL and SQLite (any NULL in the chain = NULL result), while CONCAT() in MySQL, SQL Server, and PostgreSQL treats NULLs as empty strings. Oracle's CONCAT() only takes two arguments. CONCAT_WS() (MySQL 2017+, SQL Server 2017+) is the cleanest option when you have a separator and want to skip NULLs automatically.

Standard Syntax

SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;

Version Support

MySQL: Native in all listed versions PostgreSQL: Native in all listed versions SQL Server: Native since 2012 Oracle: Native in all listed versions SQLite: Native since 3.44.0

Per-Database Syntax & Notes

MySQL Native syntax

CONCAT() ignores NULL arguments (treats them as empty string). CONCAT_WS(sep, ...) skips NULLs and adds a separator between non-null values.

SELECT CONCAT('Hello', ' ', 'World'); -- 'Hello World' SELECT CONCAT('a', NULL, 'b'); -- 'ab' (NULL silently ignored) SELECT CONCAT_WS(', ', 'Alice', NULL, 'Bob'); -- 'Alice, Bob'

PostgreSQL Native syntax

CONCAT() ignores NULLs (like MySQL). The || operator is the standard alternative but propagates NULLs — 'a' || NULL = NULL. Use CONCAT() or COALESCE() when NULL safety matters.

SELECT CONCAT('Hello', ' ', 'World'); -- 'Hello World' SELECT 'Hello' || ' ' || 'World'; -- 'Hello World' SELECT 'a' || NULL; -- NULL SELECT CONCAT('a', NULL, 'b'); -- 'ab'

SQL Server Native syntax

CONCAT() added in SQL Server 2012 and treats NULLs as empty strings. Before 2012, use + operator — but + propagates NULLs unless SET CONCAT_NULL_YIELDS_NULL OFF. CONCAT_WS() added in SQL Server 2017.

SELECT CONCAT('Hello', ' ', 'World'); -- 'Hello World' SELECT CONCAT('a', NULL, 'b'); -- 'ab' SELECT 'Hello' + ' ' + 'World'; -- 'Hello World' (pre-2012) SELECT CONCAT_WS(', ', 'Alice', NULL, 'Bob'); -- 'Alice, Bob' (2017+)

Oracle Native syntax

CONCAT() accepts exactly two arguments. For more than two strings, use the || operator or nest CONCAT() calls. In Oracle, NULL is treated as empty string in string concatenation (|| propagates, but CONCAT ignores).

SELECT CONCAT('Hello', ' World') FROM DUAL; -- 'Hello World' SELECT 'Hello' || ' ' || 'World' FROM DUAL; -- 'Hello World' SELECT CONCAT(CONCAT('a', 'b'), 'c') FROM DUAL; -- 'abc'

SQLite Native syntax

CONCAT() added in SQLite 3.44.0 (Nov 2023). Before that, use the || operator exclusively. || propagates NULLs — use COALESCE() to guard against them.

SELECT CONCAT('Hello', ' ', 'World'); -- 3.44.0+ SELECT 'Hello' || ' ' || 'World'; -- all versions SELECT COALESCE(name, '') || ' ' || COALESCE(suffix, '') FROM tbl;