SQL String Functions: UPPER, SUBSTRING, TRIM & More
7 min read · Updated August 28, 2026
Text arrives messy: inconsistent capitalisation, stray spaces, values glued together that you need apart, values apart that you need together. String functions are SQL's toolkit for cleaning and reshaping text inside the query, so the data comes back the way the report needs it. This guide covers the core set that exists, under one spelling or another, in every major database.
Changing case: UPPER and LOWER
SELECT UPPER(first_name) AS shouted, LOWER(email) AS normalised
FROM Employees
LIMIT 3;
Cosmetics are the obvious use; the important one is case-insensitive comparison. Whether 'Austin' equals 'austin' depends on the database's collation settings — but lower-casing both sides makes the comparison behave the same everywhere:
SELECT company, city
FROM Customers
WHERE LOWER(city) = 'austin';
Measuring length: LEN and LENGTH
SELECT first_name, LEN(first_name) AS name_length
FROM Employees
ORDER BY name_length DESC
LIMIT 5;
The spelling is the annoying part: SQL Server and this playground's engine use LEN, while
MySQL, PostgreSQL and SQLite use LENGTH. The behaviour is the same. Typical uses are data
quality checks — finding suspiciously short names, or values that overflow a field limit.
Slicing text: SUBSTRING
SELECT email, SUBSTRING(email, 1, 5) AS first_five
FROM Employees
LIMIT 3;
The arguments are the string, the starting position, and how many characters to take — and SQL counts from 1, not 0, which surprises everyone arriving from a programming language. Combined with other functions it builds things like initials:
SELECT company, UPPER(SUBSTRING(company, 1, 1)) AS initial
FROM Customers
LIMIT 5;
Find and replace: REPLACE
SELECT REPLACE(email, '@example.com', '') AS mailbox
FROM Employees
LIMIT 4;
REPLACE swaps every occurrence of one substring for another — here replacing the domain with nothing, which strips it. It only changes the query's output; the stored data is untouched unless you put the expression inside an UPDATE.
Trimming whitespace: TRIM
SELECT TRIM(' SQL Practice ') AS trimmed;
TRIM removes leading and trailing spaces — the classic cure for data pasted in from spreadsheets, where
'Sales ' quietly fails to equal 'Sales'. Most databases also offer LTRIM and
RTRIM for one side only.
Joining text: || and CONCAT
SELECT first_name || ' ' || last_name AS full_name,
CONCAT(last_name, ', ', first_name) AS sorted_name
FROM Employees
LIMIT 3;
Both forms work here, which is convenient because the real world splits: || is the SQL
standard (PostgreSQL, SQLite, Oracle), while MySQL wants CONCAT() and SQL Server historically
used +. One behavioural difference worth knowing: with ||, a NULL anywhere makes
the whole result NULL, whereas CONCAT in most databases treats NULL as an empty string.
Handling missing text: COALESCE and NULLIF
Not strictly string functions — they work on any type — but text is where you meet them daily. COALESCE returns the first non-NULL argument, which is how a NULL becomes a readable label:
SELECT e.first_name, COALESCE(m.first_name, 'no manager') AS reports_to
FROM Employees e
LEFT JOIN Employees m ON m.emp_id = e.manager_id
LIMIT 6;
NULLIF is its mirror: NULLIF(a, b) returns NULL when the two arguments are equal, otherwise
returns the first. Its everyday job is turning junk placeholder values — empty strings, 'N/A' — back into
honest NULLs before COALESCE or aggregates handle them:
SELECT NULLIF('same', 'same') AS becomes_null, NULLIF('a', 'b') AS stays_a;
Try it yourself
Every example above runs against the sample database as-is. Try chaining functions — UPPER inside SUBSTRING inside REPLACE — and watch how they compose.
Open the PlaygroundOne habit worth building
Wrapping a column in a function inside WHERE — as in LOWER(city) = 'austin' — is
fine on small data, but on a large indexed table it can stop the database using the index, because the
index stores city, not LOWER(city). Production databases solve this with
case-insensitive collations or function-based indexes. Nothing to act on while learning — just remember
that where you put the function matters more as tables grow.
Frequently asked questions
What are string functions in SQL?
Built-in functions that transform text values inside a query: changing case, measuring length, slicing out substrings, replacing text, trimming spaces and joining values together. They change what the query returns, not what the table stores.
What is the difference between LEN and LENGTH?
Only the spelling. SQL Server uses LEN; MySQL, PostgreSQL and SQLite use LENGTH. Both return the number of characters in the string. If one spelling errors, try the other.
Does SUBSTRING start counting at 0 or 1?
At 1. SUBSTRING(email, 1, 5) takes the first five characters. Starting positions in SQL are 1-based across every major database, unlike most programming languages.
How do I concatenate strings in SQL?
The standard operator is ||, used by PostgreSQL, SQLite and Oracle. MySQL uses the CONCAT() function, and SQL Server uses + or CONCAT(). Watch NULL handling: || propagates NULL, while CONCAT usually treats NULL as an empty string.
Do string functions change the data stored in the table?
No. In a SELECT they only shape the output. To change stored values, use the same expression inside an UPDATE statement — for example SET email = LOWER(email).
How do I compare text case-insensitively in SQL?
The portable way is to apply LOWER (or UPPER) to both sides of the comparison. Whether plain = ignores case depends on the database and its collation: MySQL usually does, PostgreSQL does not.