Converts every character to lowercase. Most important function in data cleaning — fixes casing mismatches that cause GROUP BY to split one person into two rows.
'ramesh shrestha' and 'Ramesh Shrestha'. Without LOWER, a GROUP BY treats them as two different drivers.
Converts every character to uppercase. Less common in data cleaning but useful for status codes, codes, and labels where you want a canonical uppercase form.
Removes leading and trailing spaces (both sides). The default behaviour — what you want 95% of the time for CSV data where fields often carry padding.
LTRIM removes spaces from the left side only. RTRIM removes from the right only. Rarely needed vs TRIM but useful when only one side has the problem.
Replaces every occurrence of a substring with another. Case-sensitive. Great for fixing known typos, removing characters, or swapping separators.
Joins multiple strings into one. Also written with the || operator. CONCAT ignores NULLs; || returns NULL if any part is NULL.
Returns the number of characters in a string. Useful for validation — detect values that are suspiciously short/long before inserting them.
Returns the first non-NULL value from its arguments. Absolutely essential in migration — fills in missing values rather than letting NULLs propagate.
LIKE matches a pattern — % means any characters, _ means exactly one character. ILIKE is the same but case-insensitive. Use ILIKE for user-facing searches.
% = zero or more any characters. _ = exactly one any character. Example: LIKE 'R_mesh' matches 'Ramesh' but not 'Raamesh'.
Returns the position (index) of a substring inside a string. Returns 0 if not found. Strings in PostgreSQL are 1-indexed. Both functions do the same thing, different syntax.
Returns TRUE or FALSE. Cleaner than LIKE for simple prefix/suffix checks. STARTS_WITH is case-sensitive. For case-insensitive prefix check, use ILIKE 'prefix%' instead.
Extracts a portion of a string starting at position pos for len characters. Positions are 1-indexed. Can also accept a regex pattern (see Panel 4).
LEFT returns the first n characters. RIGHT returns the last n characters. Simpler than SUBSTRING when you just need the beginning or end.
Splits a string on a delimiter and returns the nth part (1-indexed). Extremely useful for CSV-style columns, email addresses, or any delimited data stored as text.
Pads a string to a target length by adding characters on the left or right. Useful for formatting IDs, codes, and fixed-width output columns.
| function | call | result |
|---|---|---|
| LEFT | LEFT('Ramesh Shrestha', 6) | 'Ramesh' |
| RIGHT | RIGHT('Ramesh Shrestha', 8) | 'Shrestha' |
| SUBSTRING | SUBSTRING('Ramesh Shrestha' FROM 8 FOR 8) | 'Shrestha' |
| SPLIT_PART | SPLIT_PART('Ramesh Shrestha', ' ', 1) | 'Ramesh' |
| SPLIT_PART | SPLIT_PART('Ramesh Shrestha', ' ', 2) | 'Shrestha' |
| LENGTH | LENGTH('Ramesh Shrestha') | 15 |
A regex is a pattern that describes a set of strings. Instead of writing REPLACE('abc', 'a', '') for one specific character, a regex lets you say "remove any digit" or "remove all characters that aren't letters" — applying to millions of different variations with one expression.
| pattern | what it matches | example match |
|---|---|---|
| [0-9] | any single digit | '9' in 'NP9841' |
| [^0-9] | any character that is NOT a digit | 'N', 'P' in 'NP9841' |
| [a-zA-Z] | any letter | 'R' in 'Ramesh' |
| \s | any whitespace (space, tab, newline) | the space in 'New Road' |
| \s+ | one or more whitespace characters | ' ' (multiple spaces) |
| [^a-zA-Z\s] | anything not a letter or space | digits, dashes, brackets |
| ^ | start of string | anchors the pattern to the beginning |
| $ | end of string | anchors the pattern to the end |
Replaces parts of a string that match a regex pattern. The flags argument is optional: 'g' replaces all matches (not just the first), 'i' makes it case-insensitive.
| REPLACE | REGEXP_REPLACE | |
|---|---|---|
| Use when | You know the exact string to find | You need to match a pattern or character class |
| Example need | Fix one specific typo everywhere | Remove all digits, collapse spaces, strip symbols |
| Case sensitive | Always yes | Yes by default; add 'i' flag for insensitive |
| Replace all | Always replaces all | Only all if you pass 'g' flag |
| Example | REPLACE(phone,'-','') | REGEXP_REPLACE(phone,'[^0-9]','','g') |
These are the actual patterns you'll write in the Week 2 migration script. Each one combines multiple string functions to solve a real problem in the rides.csv data.
'') are not the same as NULL in PostgreSQL. Use NULLIF to convert empty strings to NULL, then COALESCE to provide a default.| function | what it does | migration use case |
|---|---|---|
| LOWER(s) | all lowercase | normalise names before lookup |
| UPPER(s) | all uppercase | canonical status codes |
| INITCAP(s) | Title Case every word | clean display name after LOWER |
| TRIM(s) | remove leading + trailing spaces | every column before comparing or inserting |
| LTRIM(s) | leading spaces only | rarely needed; use TRIM instead |
| RTRIM(s) | trailing spaces only | rarely needed; use TRIM instead |
| function | what it does | migration use case |
|---|---|---|
| REPLACE(s, from, to) | swap exact substring | fix known typos in city names |
| REGEXP_REPLACE(s, pat, rep, 'g') | pattern-based replace | remove symbols, collapse spaces, strip non-letters |
| CONCAT(a, b, …) | join strings | build full names from first+last, add labels |
| a || b | join strings (operator) | same as CONCAT; returns NULL if any part is NULL |
| function | what it does | migration use case |
|---|---|---|
| LENGTH(s) | character count | validate minimum name length before insert |
| LEFT(s, n) | first n chars | extract prefix codes, country codes |
| RIGHT(s, n) | last n chars | extract suffix, two-letter codes |
| SUBSTRING(s FROM p FOR n) | n chars starting at position p | extract year from date string |
| SPLIT_PART(s, delim, n) | nth segment after splitting on delimiter | parse 'City, Province' into parts |
| POSITION(sub IN s) | position of substring, 0 if not found | check if '@' present to validate emails |
| STRPOS(s, sub) | same as POSITION, different syntax | same use cases |
| LPAD(s, n, fill) | left-pad to length n | zero-pad integer IDs for display |
| RPAD(s, n, fill) | right-pad to length n | align fixed-width output columns |
| function | what it does | migration use case |
|---|---|---|
| COALESCE(v1, v2, …) | first non-NULL value | default value for missing payment_method, notes |
| NULLIF(v, compare) | returns NULL if v = compare, else v | convert empty string '' to NULL before COALESCE |
| function / operator | what it does | migration use case |
|---|---|---|
| col LIKE 'pattern' | pattern match, case-sensitive | filter rows by prefix/suffix |
| col ILIKE 'pattern' | pattern match, case-insensitive | case-safe search in WHERE clauses |
| STARTS_WITH(s, prefix) | true if s starts with prefix | check status starts with 'comp' |
INITCAP(LOWER(TRIM(column_name)))