SQL String Concatenation: MySQL, PostgreSQL, SQLite, SQL Server & Oracle
Compare SQL string concatenation operators and functions across MySQL, PostgreSQL, SQLite, SQL Server, MariaDB, and Oracle with NULL handling rules.
String concatenation syntax and NULL behavior differ significantly across relational database management systems. An operator that concatenates strings in one database may perform numeric addition or logical evaluation in another, and NULL arguments can either turn the entire result into NULL or be ignored as empty text.
These examples compare the concatenation operators, standard functions, delimiter handling, and NULL propagation rules across MySQL, MariaDB, PostgreSQL, SQLite, SQL Server, and Oracle.
Quick reference
| Database | Primary operator | Concatenation function | NULL handling with function |
Delimited helper |
|---|---|---|---|---|
| MySQL / MariaDB | CONCAT() (or || in PIPES_AS_CONCAT mode) |
CONCAT(s1, s2, ...) |
Any NULL argument produces NULL |
CONCAT_WS(sep, s1, s2, ...) |
| PostgreSQL | || |
concat(s1, s2, ...) |
Treats NULL as empty string '' |
concat_ws(sep, s1, s2, ...) |
| SQLite | || |
|| operator |
Any NULL operand produces NULL |
group_concat(col, sep) |
| SQL Server | + or CONCAT() |
CONCAT(s1, s2, ...) |
Converts NULL to empty string '' |
CONCAT_WS(sep, s1, s2, ...) |
| Oracle | || |
CONCAT(s1, s2) (2 args only) |
Treats NULL and '' as empty string |
Custom / LISTAGG |
MySQL and MariaDB
In standard MySQL and MariaDB configurations, the plus sign + performs arithmetic addition, not concatenation. Attempting 'Hello' + 'World' converts non-numeric strings to 0 and returns 0. Similarly, || functions as the logical OR operator by default unless the PIPES_AS_CONCAT SQL mode is active.
Use the CONCAT() function to join strings:
SELECT CONCAT('Post', '#', 42) AS result;
result
-------
Post#42MySQL NULL handling and CONCAT_WS()
If any argument passed to CONCAT() is NULL, MySQL and MariaDB return NULL:
SELECT CONCAT('User: ', NULL) AS result;
result
-------
NULLTo concatenate strings while skipping NULL entries or joining them with a separator, use CONCAT_WS():
SELECT CONCAT_WS(' ', 'Jane', NULL, 'Doe') AS full_name;
full_name
---------
Jane DoeSee the MySQL 8.4 CONCAT() reference and SQLiz’s MySQL CONCAT() guide and MariaDB CONCAT() guide.
PostgreSQL
PostgreSQL supports both the ANSI SQL string concatenation operator || and the concat() function. Non-string inputs with concat() are automatically converted to text representations.
SELECT 'Item ' || 101 AS op_result,
concat('Item ', 101) AS fn_result;
op_result | fn_result
----------+----------
Item 101 | Item 101The || versus concat() difference in PostgreSQL
A key distinction in PostgreSQL is how NULL is treated:
- The
||operator returnsNULLif any operand isNULL. - The
concat()andconcat_ws()functions treatNULLarguments as empty strings, preserving the remaining content.
SELECT 'alpha' || NULL AS op_null,
concat('alpha', NULL, 'beta') AS fn_null;
op_null | fn_null
--------+----------
NULL | alphabetaUse concat_ws() when inserting a separator between non-null values:
SELECT concat_ws(', ', 'Red', NULL, 'Blue') AS colors;
colors
----------
Red, BlueSee PostgreSQL’s string functions documentation and SQLiz’s PostgreSQL concat() reference.
SQLite
SQLite uses the standard SQL double-pipe || operator for string concatenation. The + operator in SQLite is strictly numeric addition.
SELECT 'Version: ' || 3 || '.' || 46 AS version_string;
version_string
--------------
Version: 3.46SQLite NULL handling
In SQLite, concatenating any value with NULL using || returns NULL:
SELECT 'Prefix: ' || NULL AS result;
result
------
NULLIf you need to skip NULL values or replace them with fallback text in SQLite, combine || with the ifnull() or coalesce() function:
SELECT 'Prefix: ' || ifnull(NULL, '') AS result;
result
-------
Prefix: See SQLite’s operators documentation.
SQL Server (Transact-SQL)
SQL Server provides both the + operator and the built-in CONCAT() and CONCAT_WS() functions (introduced in SQL Server 2012 and 2017).
Using the + operator requires all arguments to be compatible data types, or explicitly cast to character types. If SET CONCAT_NULL_YIELDS_NULL is ON (default), concatenating NULL produces NULL:
SELECT 'Order: ' + CAST(1001 AS varchar(10)) AS order_num;
order_num
-----------
Order: 1001SQL Server CONCAT() and CONCAT_WS()
CONCAT() in SQL Server automatically converts non-string arguments to strings and converts NULL values to empty strings '':
SELECT CONCAT('Invoice #', 500, ' - ', NULL, 'Paid') AS invoice_status;
invoice_status
-------------------
Invoice #500 - PaidUse CONCAT_WS() to join values with a specified delimiter while ignoring NULL entries:
SELECT CONCAT_WS('-', '2026', '10', '02') AS date_slug;
date_slug
----------
2026-10-02See Microsoft’s CONCAT (Transact-SQL) documentation and SQLiz’s SQL Server CONCAT() reference.
Oracle
Oracle Database uses the ANSI SQL || operator as its primary string concatenation mechanism.
SELECT 'Employee: ' || 205 AS employee_tag FROM dual;
EMPLOYEE_TAG
------------
Employee: 205Oracle’s two-argument CONCAT() limit
Unlike MySQL, PostgreSQL, or SQL Server, Oracle’s CONCAT(char1, char2) function accepts strictly two arguments. To concatenate three or more values using the function, calls must be nested:
-- Nested function calls:
SELECT CONCAT(CONCAT('A', 'B'), 'C') AS nested_concat FROM dual;
-- Idiomatic operator syntax:
SELECT 'A' || 'B' || 'C' AS pipe_concat FROM dual;
Oracle NULL and empty string semantics
In Oracle Database, an empty string '' is treated as NULL. However, the concatenation operator || treats NULL operands as zero-length strings rather than causing the whole result to become NULL:
SELECT 'Start-' || NULL || '-End' AS result FROM dual;
RESULT
---------
Start--EndSee Oracle’s Concatenation Operator manual and SQLiz’s Oracle CONCAT() reference.
Key takeaways and portability tips
- Avoid
+for string concatenation: In MySQL, MariaDB, SQLite, and Oracle,+is an arithmetic operator. Only SQL Server uses+for strings, and even in SQL Server,CONCAT()is preferred because it handlesNULLand data type conversion automatically. - Be deliberate about
NULLhandling: If you use||in PostgreSQL or SQLite, orCONCAT()in MySQL, anyNULLoperand results in aNULLoutput. UseCONCAT_WS()or wrap nullable columns inCOALESCE()to avoid unexpected blank records. - Delimiter joins: When joining multiple address lines, names, or slugs, use
CONCAT_WS()where supported (MySQL, MariaDB, PostgreSQL, SQL Server).