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.
| Function | Returns | Example → result |
|---|---|---|
LEN(s) | LEN('Sand ') → 4 | |
LEFT(s, n) / RIGHT(s, n) | LEFT('Sand 25 kg', 4) → Sand | |
SUBSTRING(s, start, length) | SUBSTRING('Plywood', 4, 4) → wood | |
CHARINDEX(find, s [, start]) | CHARINDEX('@', 'ben@x.com') → 4 | |
REPLACE(s, find, with) | REPLACE('0113 496', ' ', '') → 0113496 | |
UPPER(s) / LOWER(s) | UPPER('york') → YORK | |
TRIM(s) / LTRIM / RTRIM | TRIM(' 7 ') → 7 | |
CONCAT(a, b, …) | CONCAT('A', NULL, 'B') → AB | |
CONCAT_WS(sep, a, b, …) | CONCAT_WS(', ', 'Leeds', NULL, 'UK') → Leeds, UK | |
REPLICATE(s, n) | REPLICATE('ab', 3) → ababab |
Reshaping names
SELECT FirstName, LastName, UPPER(LastName) + N', ' + LEFT(FirstName, 1) + N'.' AS Label, LEN(FirstName + LastName) AS LettersFROM dbo.CustomersWHERE CustomerId <= 4;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:
SELECT Name, CHARINDEX(N' ', Name) AS FirstSpace, LEFT(Name, CHARINDEX(N' ', Name + N' ') - 1) AS FirstWordFROM dbo.ProductsWHERE CategoryId IN (2, 3);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
@. Ben has no email, so every expression on it is NULL, without any error:
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);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:
SELECT FirstName, REPLACE(Phone, ' ', '') AS DialString, CONCAT_WS(N' | ', City, Email, Phone) AS ContactFROM dbo.CustomersWHERE CustomerId IN (2, 3, 5);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:
SELECT TRIM(value) AS ItemFROM STRING_SPLIT(N'cement, sand ,timber, paint', N',');Item ------ cement sand timber paint
Collation: does case matter?
'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:
SELECT IIF(N'Leeds' = N'LEEDS', 'equal', 'different') AS DefaultCollation, IIF(N'Leeds' = N'LEEDS' COLLATE Latin1_General_CS_AS, 'equal', 'different') AS CaseSensitive;DefaultCollation CaseSensitive ---------------- ------------- equal different
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
Show the solution
SELECT LastName + N', ' + LEFT(FirstName, 1) + N'.' AS Name, LEFT(Email, CHARINDEX(N'@', Email) - 1) AS UserNameFROM dbo.Customers;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.