All 40 lessons
Lesson 9 of 40 · SQL Functions
SQL String Functions
By Skillancy Editorial Team
Every example runs on the ShopKart dataset, already loaded in the free SQL Compiler. Click Try it in the SQL Compiler under a query to open it there, then press Run.
String functions let you clean, combine and extract text inside a query. Analysts use them constantly: standardising city names, pulling the domain out of an email, or building a display label.
Quick reference
| Function | What it does | Example | Result |
|---|---|---|---|
UPPER(s) / LOWER(s) | change case | UPPER('delhi') | DELHI |
INITCAP(s) | capitalise each word (PostgreSQL) | INITCAP('new delhi') | New Delhi |
LENGTH(s) | number of characters | LENGTH('Pune') | 4 |
CONCAT(a, b, ...) or a || b | join text | 'Shop' || 'Kart' | ShopKart |
SUBSTRING(s, start, len) | part of a string | SUBSTRING('ShopKart', 5, 4) | Kart |
LEFT(s, n) / RIGHT(s, n) | first / last n characters | RIGHT('9876543210', 4) | 3210 |
TRIM(s) | remove leading/trailing spaces | TRIM(' UPI ') | UPI |
REPLACE(s, from, to) | replace text | REPLACE('a-b', '-', ' ') | a b |
POSITION(x IN s) | where x starts (0 if absent) | POSITION('@' IN 'a@b.com') | 2 |
SPLIT_PART(s, d, n) | nth piece after splitting (PostgreSQL) | SPLIT_PART('a@b.com', '@', 2) | b.com |
Examples
1. Change case
SELECT customer_name,
UPPER(customer_name) AS upper_name,
LOWER(city) AS city_lower
FROM customers
LIMIT 3;Try it in the SQL CompilerResult:
| customer_name | upper_name | city_lower |
|---|---|---|
| Aarav Sharma | AARAV SHARMA | bengaluru |
| Priya Nair | PRIYA NAIR | kochi |
| Rohan Gupta | ROHAN GUPTA | delhi |
(3 rows)
2. Combine columns
Build a label like "Aarav Sharma (Bengaluru)":
SELECT customer_name || ' (' || city || ')' AS customer_label
FROM customers
LIMIT 3;Try it in the SQL CompilerResult:
| customer_label |
|---|
| Aarav Sharma (Bengaluru) |
| Priya Nair (Kochi) |
| Rohan Gupta (Delhi) |
(3 rows)
CONCAT does the same and is safer with NULLs, because it treats them as empty text:
SELECT customer_name,
customer_name || ' - ' || phone AS with_pipe,
CONCAT(customer_name, ' - ', phone) AS with_concat
FROM customers
WHERE phone IS NULL;Try it in the SQL CompilerResult:
| customer_name | with_pipe | with_concat |
|---|---|---|
| Rohan Gupta | NULL | Rohan Gupta - |
| Karan Mehta | NULL | Karan Mehta - |
(2 rows)
3. Extract part of a string
The first name is everything before the space:
SELECT customer_name,
SPLIT_PART(customer_name, ' ', 1) AS first_name,
LEFT(customer_name, 1) AS initial
FROM customers
LIMIT 4;Try it in the SQL CompilerResult:
| customer_name | first_name | initial |
|---|---|---|
| Aarav Sharma | Aarav | A |
| Priya Nair | Priya | P |
| Rohan Gupta | Rohan | R |
| Sneha Reddy | Sneha | S |
(4 rows)
4. Get the email domain
SELECT email,
SUBSTRING(email, POSITION('@' IN email) + 1) AS domain
FROM customers
WHERE email IS NOT NULL
LIMIT 5;Try it in the SQL CompilerResult:
| domain | |
|---|---|
| aarav.sharma@gmail.com | gmail.com |
| priya.nair@yahoo.com | yahoo.com |
| rohan.g@outlook.com | outlook.com |
| sneha.reddy@gmail.com | gmail.com |
| vikram.singh@gmail.com | gmail.com |
(5 rows)
SUBSTRING with no length returns everything from the start position to the end.
5. Mask a phone number
Show only the last four digits, as you would on an order confirmation:
SELECT customer_name,
'XXXXXX' || RIGHT(phone, 4) AS masked_phone
FROM customers
WHERE phone IS NOT NULL
LIMIT 3;Try it in the SQL CompilerResult:
| customer_name | masked_phone |
|---|---|
| Aarav Sharma | XXXXXX3210 |
| Priya Nair | XXXXXX2345 |
| Sneha Reddy | XXXXXX6655 |
(3 rows)
6. Clean messy text
Real data often arrives with extra spaces and inconsistent case. TRIM + INITCAP fixes it:
SELECT ' new delhi ' AS raw_value,
INITCAP(TRIM(' new delhi ')) AS cleaned,
LENGTH(' new delhi ') AS raw_length;Try it in the SQL CompilerResult:
| raw_value | cleaned | raw_length |
|---|---|---|
| new delhi | New Delhi | 12 |
(1 row)
7. Replace text
SELECT product_name,
REPLACE(product_name, ' ', '-') AS url_slug
FROM products
LIMIT 3;Try it in the SQL CompilerResult:
| product_name | url_slug |
|---|---|
| Redmi Note 13 Pro | Redmi-Note-13-Pro |
| boAt Airdopes 141 | boAt-Airdopes-141 |
| Samsung 43" Smart TV | Samsung-43"-Smart-TV |
(3 rows)
Common mistakes
||with a NULL column. One NULL makes the whole result NULL. UseCONCATorCOALESCE.- Counting positions from 0. SQL strings start at position 1.
- Comparing untrimmed text.
'UPI 'does not equal'UPI'. Trim before you compare or group.
Practice question
For each customer, show their name and the username part of their email (before the @). Skip customers without an email.
Show solution
SELECT customer_name,
SPLIT_PART(email, '@', 1) AS username
FROM customers
WHERE email IS NOT NULL
LIMIT 5;Try it in the SQL CompilerResult:
| customer_name | username |
|---|---|
| Aarav Sharma | aarav.sharma |
| Priya Nair | priya.nair |
| Rohan Gupta | rohan.g |
| Sneha Reddy | sneha.reddy |
| Vikram Singh | vikram.singh |
(5 rows)
Key takeaways
UPPER,LOWERandINITCAPstandardise case.||andCONCATjoin text;CONCATignores NULLs.SUBSTRING,LEFT,RIGHTandSPLIT_PARTextract pieces.TRIMandREPLACEclean messy values before analysis.
Frequently asked questions
How do I concatenate strings in SQL?
Use CONCAT(a, b) or the || operator in PostgreSQL. CONCAT treats NULL as an empty string, while a || NULL returns NULL. In SQL Server you can also use +.
Do SQL string positions start at 0 or 1?
At 1. SUBSTRING('ShopKart', 1, 4) returns 'Shop'.
How do I split a string in SQL?
In PostgreSQL use SPLIT_PART(text, delimiter, n). MySQL uses SUBSTRING_INDEX, and SQL Server uses STRING_SPLIT.
Keep learning SQL
One email a week with SQL and analytics guides, new practice questions and cohort dates. No spam, unsubscribe anytime.
Prefer a one-page summary? Download the free SQL cheat sheet (PDF)