Skip to content
Laviyx Learn

Try

SQL course menu

SQL String Functions: UPPER, LOWER, LENGTH, SUBSTRING, TRIM, REPLACE, CONCAT

Learn the most useful SQL string functions with examples: change case, measure length, extract parts of text, trim spaces, replace text, find positions, and join strings, with differences between databases.

Beginner8 min readUpdated
On this page

Text data is rarely perfect. Names arrive in random capitalisation, emails contain the domain you want to group by, and codes have stray spaces. String functions let you clean, reshape and inspect text directly in your queries.

The example table#

idnamecityemail
1AshaMumbaiasha@company.com
2RaviBengalururavi@company.com
3MeeraPunemeera@company.com
4JohnMumbaiNULL
5PriyaDelhipriya@company.com

Quick reference#

TaskStandard / PostgreSQLMySQLSQL ServerSQLite
Upper / lower caseUPPER(s), LOWER(s)samesamesame
LengthLENGTH(s)CHAR_LENGTH(s)LEN(s)LENGTH(s)
Part of a stringSUBSTRING(s FROM 1 FOR 3) or SUBSTR(s, 1, 3)SUBSTRING(s, 1, 3)SUBSTRING(s, 1, 3)SUBSTR(s, 1, 3)
Remove spacesTRIM(s)sameTRIM(s) (2017+)same
Replace textREPLACE(s, a, b)samesamesame
Find positionPOSITION('@' IN s)LOCATE('@', s)CHARINDEX('@', s)INSTR(s, '@')
Join stringsa || b or CONCAT(a, b)CONCAT(a, b)a + b or CONCAT(a, b)a || b

The examples below use the forms that work in PostgreSQL and SQLite; check the table for your database.

UPPER, LOWER and LENGTH#

SQLRun
SELECT name,
       UPPER(name)  AS upper_name,
       LOWER(name)  AS lower_name,
       LENGTH(name) AS len
FROM employees
WHERE id <= 3;
Output
name  | upper_name | lower_name | len
------+------------+------------+----
Asha  | ASHA       | asha       | 4
Ravi  | RAVI       | ravi       | 4
Meera | MEERA      | meera      | 5

LOWER is the classic tool for case-insensitive search: WHERE LOWER(email) = LOWER('Asha@Company.com').

Joining strings (concatenation)#

SQLRun
SELECT name || ' (' || city || ')' AS label
FROM employees
WHERE id IN (1, 5);
Output
label
-------------
Asha (Mumbai)
Priya (Delhi)

In MySQL write CONCAT(name, ' (', city, ')'); || means OR there by default.

Extracting part of a string: SUBSTRING#

SUBSTR(text, start, length) returns length characters starting at position start. Positions start at 1, not 0:

SQLRun
SELECT name, SUBSTR(name, 1, 3) AS short
FROM employees
WHERE id <= 3;
Output
name  | short
------+------
Asha  | Ash
Ravi  | Rav
Meera | Mee

Leave out the length to take everything to the end of the string.

Finding a position#

Combine a position function with SUBSTR to split text at a character. The domain of each email:

SQLRun
SELECT email,
       SUBSTR(email, INSTR(email, '@') + 1) AS domain
FROM employees
WHERE email IS NOT NULL;
Output
email             | domain
------------------+------------
asha@company.com  | company.com
ravi@company.com  | company.com
meera@company.com | company.com
priya@company.com | company.com

INSTR(email, '@') finds where the @ is (5 for asha@...), and SUBSTR takes everything after it. PostgreSQL also offers SPLIT_PART(email, '@', 2), and MySQL SUBSTRING_INDEX(email, '@', -1).

TRIM: remove extra spaces#

Imported data often has leading or trailing spaces that make 'Pune ' different from 'Pune':

SQLRun
SELECT TRIM('   hello   ') AS trimmed,
       LENGTH(TRIM('   hello   ')) AS len;
Output
trimmed | len
--------+----
hello   | 5

LTRIM and RTRIM remove spaces from only the left or right side.

REPLACE#

REPLACE(text, find, replace_with) swaps every occurrence:

SQLRun
SELECT name, REPLACE(category, 'Electronics', 'Tech') AS category
FROM products
WHERE category = 'Electronics';
Output
name       | category
-----------+---------
Laptop     | Tech
Headphones | Tech
Monitor    | Tech

Combined with UPDATE, it can clean a whole column: UPDATE customers SET phone = REPLACE(phone, ' ', '');

Nesting functions#

Functions can be nested, innermost first. Fixing the capitalisation of a name:

SQLRun
SELECT UPPER(SUBSTR('aSHA', 1, 1)) || LOWER(SUBSTR('aSHA', 2)) AS fixed;
Output
fixed
-----
Asha

PostgreSQL and Oracle have a built-in INITCAP('aSHA') for this.

Common mistakes#

Practice#

Practice exercise

For every employee with an email, return their name, email, and the username part of the email (everything before the @).

Show hint

The username starts at position 1 and is INSTR(email, '@') - 1 characters long.

Show solution
SQLRun
SELECT name,
       email,
       SUBSTR(email, 1, INSTR(email, '@') - 1) AS username
FROM employees
WHERE email IS NOT NULL;
Output
name  | email             | username
------+-------------------+---------
Asha  | asha@company.com  | asha
Ravi  | ravi@company.com  | ravi
Meera | meera@company.com | meera
Priya | priya@company.com | priya

In PostgreSQL, SPLIT_PART(email, '@', 1) gives the same result.

Key takeaway#

Finished this lesson?