<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. SQL
  3. Functions and expressions
All lessons in this course

Lesson 13 of 54 15 minBeginner

Working with text: string functions

Measure, cut, search, replace and join text with T-SQL’s string functions. Positions start at 1, LEN ignores trailing spaces, and NULL needs care.

Text arrives messy: names in the wrong case, phone numbers with spaces, emails you need the domain of. T-SQL has a toolbox of string functions for cleaning and reshaping it inside a query. Two rules hold for all of them: positions start at 1, and a NULL input gives a NULL result (except where noted).

Interactive

String functions, character by character

SUBSTRING('Plywood sheet 18 mm', 9, 5)→'sheet'
SUBSTRING(text, start, length): 5 characters starting at position 9. Going past the end is not an error; you get what is there.
FunctionReturnsExample → result
LEN(s)number of characters, ignoring trailing spacesLEN('Sand ') → 4
LEFT(s, n) / RIGHT(s, n)the first / last n charactersLEFT('Sand 25 kg', 4) → Sand
SUBSTRING(s, start, length)length characters from position startSUBSTRING('Plywood', 4, 4) → wood
CHARINDEX(find, s [, start])position of find in s, or 0CHARINDEX('@', 'ben@x.com') → 4
REPLACE(s, find, with)s with every find replacedREPLACE('0113 496', ' ', '') → 0113496
UPPER(s) / LOWER(s)changed caseUPPER('york') → YORK
TRIM(s) / LTRIM / RTRIMs without surrounding spacesTRIM(' 7 ') → 7
CONCAT(a, b, …)joined text; NULL counts as emptyCONCAT('A', NULL, 'B') → AB
CONCAT_WS(sep, a, b, …)joined with a separator; NULLs skippedCONCAT_WS(', ', 'Leeds', NULL, 'UK') → Leeds, UK
REPLICATE(s, n)s repeated n timesREPLICATE('ab', 3) → ababab

Reshaping names

Query.sql
SELECT FirstName, LastName,       UPPER(LastName) + N', ' + LEFT(FirstName, 1) + N'.' AS Label,       LEN(FirstName + LastName) AS LettersFROM dbo.CustomersWHERE CustomerId <= 4;
Output
FirstName  LastName  Label       Letters
---------  --------  ----------  -------
Asha       Patel     PATEL, A.         9
Ben        Carter    CARTER, B.        9
Chloe      Evans     EVANS, C.        10
Dev        Singh     SINGH, D.         8

Cutting at a character

CHARINDEX finds where something is; LEFT and SUBSTRING cut there. The first word of each product name ends at the first space. Adding a space to the end (Name + N' ') makes sure there always is one:

Query.sql
SELECT Name,       CHARINDEX(N' ', Name) AS FirstSpace,       LEFT(Name, CHARINDEX(N' ', Name + N' ') - 1) AS FirstWordFROM dbo.ProductsWHERE CategoryId IN (2, 3);
Output
Name                 FirstSpace  FirstWord
-------------------  ----------  ---------
Cement 25 kg                  7  Cement
Sand 25 kg                    5  Sand
Timber 2x4 2.4 m              7  Timber
Plywood sheet 18 mm           8  Plywood

The same idea splits an email address into the part before and after the @. Ben has no email, so every expression on it is NULL, without any error:

Query.sql
SELECT FirstName, Email,       LEFT(Email, CHARINDEX(N'@', Email) - 1) AS UserName,       SUBSTRING(Email, CHARINDEX(N'@', Email) + 1, 100) AS DomainFROM dbo.CustomersWHERE CustomerId IN (1, 2, 6);
Output
FirstName  Email              UserName  Domain
---------  -----------------  --------  -----------
Asha       asha@example.com   asha      example.com
Ben        NULL               NULL      NULL
Farid      farid@example.com  farid     example.com

Cleaning and joining

REPLACE removes or swaps characters, and CONCAT_WS builds text from parts while skipping the NULL ones, so no stray commas appear:

Query.sql
SELECT FirstName,       REPLACE(Phone, ' ', '') AS DialString,       CONCAT_WS(N' | ', City, Email, Phone) AS ContactFROM dbo.CustomersWHERE CustomerId IN (2, 3, 5);
Output
FirstName  DialString   Contact
---------  -----------  -------------------------
Ben        01904555010  York | 01904 555 010
Chloe      NULL         Leeds | chloe@example.com
Ella       NULL         ella@example.com

Splitting a list

STRING_SPLIT turns one delimited string into rows, one per item. It is a table-valued function, so it goes in FROM, not in the SELECT list, and its column is called value:

Query.sql
SELECT TRIM(value) AS ItemFROM STRING_SPLIT(N'cement, sand ,timber,  paint', N',');
Output
Item
------
cement
sand
timber
paint

Collation: does case matter?

Whether 'A' = 'a', and whether REPLACE and CHARINDEX care about case, is decided by the collation of the column or database. The default for English-language installs, SQL_Latin1_General_CP1_CI_AS, is Case-Insensitive and Accent-Sensitive. You can override it for one comparison:

Query.sql
SELECT IIF(N'Leeds' = N'LEEDS', 'equal', 'different') AS DefaultCollation,       IIF(N'Leeds' = N'LEEDS' COLLATE Latin1_General_CS_AS, 'equal', 'different') AS CaseSensitive;
Output
DefaultCollation  CaseSensitive
----------------  -------------
equal             different
Quick check

What does CHARINDEX('z', 'Hammer') return?

Quick check

LEN('abc ') is…

Practice

For every customer, show their name as Patel, A. (surname, comma, initial) and the part of their email before the @ as UserName. Customers without an email should show NULL for UserName.

Show a hint

LastName + N', ' + LEFT(FirstName, 1) + N'.' for the label. LEFT(Email, CHARINDEX(N'@', Email) - 1) is NULL automatically when Email is NULL.

Show the solution
Solution.sql
SELECT LastName + N', ' + LEFT(FirstName, 1) + N'.' AS Name,       LEFT(Email, CHARINDEX(N'@', Email) - 1) AS UserNameFROM dbo.Customers;
Output
Name        UserName
----------  --------
Patel, A.   asha
Carter, B.  NULL
Evans, C.   chloe
Singh, D.   dev
Brown, E.   ella
Khan, F.    farid
Lee, G.     NULL
Müller, Z.  zoe

Remember

  • Positions start at 1; CHARINDEX returns 0 when nothing is found.
  • LEN counts characters and ignores trailing spaces; DATALENGTH counts bytes.
  • CHARINDEX + LEFT / SUBSTRING cut text at a character; SUBSTRING with a long length means “to the end”.
  • Most functions return NULL for a NULL input; CONCAT treats NULL as empty and CONCAT_WS skips it.
  • The collation decides whether comparisons, REPLACE and CHARINDEX care about case.
0 of 54 lessons completed