MySQL Built-in Functions
MySQL has hundreds of built-in functions.
Concept
MySQL has hundreds of built-in functions. This module covers the most used string, numeric, date/time, control-flow, NULL, conversion, and information functions — with MySQL-specific names and behaviors.
Why It Matters
Functions clean data, compute derived values, format output, and implement business rules directly in queries.
Syntax
SELECT FUNCTION_NAME(args) FROM ...;Example
10.1 String functions CONCAT(a, b,...) CONCAT('ECU', '-', 7) ECU-7 (NULL if any argument is NULL) CONCAT_WS(sep, a, b,...)
CONCAT_WS(', ', 'Pune', NULL, 'India') Pune, India (skips NULLs) 2 (bytes in utf8mb4) 1 (characters) UPPER, LOWER TRIM, LTRIM, RTRIM TRIM(LEADING '0' FROM s) TRIM(LEADING '0' FROM '000123') SUBSTRING(s, pos, len) SUBSTRING('EHBAUREV250000001', 10, 2) LEFT, RIGHT LEFT('P0301', 1) SUBSTRING_INDEX(s, delim, n)
SUBSTRING_INDEX('[email protected]', '@', -1) LOCATE(sub, s) / INSTR(s, sub) LOCATE('@', '[email protected]') REPLACE(s, from, to) REPLACE('1.1.0', '.', '_') LPAD, RPAD LPAD(7, 3, '0') REPEAT, REVERSE, SPACE REPEAT('-', 5) FORMAT(n, d) FORMAT(1234567.891, 2) 1,234,567.89 (string!) HEX, UNHEX, CONV CONV('1A0', 16, 10) FIND_IN_SET(s, list) FIND_IN_SET('LIN', 'CAN,LIN') GROUP_CONCAT (aggregate) 10.2 Numeric functions
ROUND(1234.567, 2) / ROUND(1234.567, -2) TRUNCATE(x, d) TRUNCATE(4.99, 1) CEIL(x) / CEILING(x) MOD(a, b) / a % b MOD(200, 12) POWER(x, y) / POW POWER(2, 10) SQRT, EXP, LN, LOG10, LOG2 random 0 ≤ x < 1 GREATEST, LEAST GREATEST(3, 9, 5) DIV (operator)
ROUND on exact values (DECIMAL) rounds half away from zero; on approximate values (FLOAT/DOUBLE) it follows the C library (usually round-half-to-even).
Physical value of a CAN signal (raw × factor + offset):
10.3 Date and time functions NOW() / CURRENT_TIMESTAMP 2026-09-29 10:15:02 (statement start time) Time at the moment of execution CURDATE() / CURRENT_DATE CURTIME() / CURRENT_TIME Current UTC time DATE(dt), TIME(dt) DATE('2026-03-10 18:30')
YEAR, MONTH, DAY, HOUR, MINUTE, SECOND DAYNAME, MONTHNAME, DAYOFWEEK (1=Sunday), WEEKDAY (0=Monday) WEEK(d, 3) / YEARWEEK(d, 3) ISO week number EXTRACT(unit FROM d) EXTRACT(YEAR_MONTH FROM '2026-03-10')
DATE_ADD(d, INTERVAL n unit) / d + INTERVAL n unit '2026-01-31' + INTERVAL 1 MONTH DATE_SUB(d, INTERVAL n unit)
DATE_SUB('2026-03-10', INTERVAL 7 DAY) DATEDIFF(d2, d1) DATEDIFF('2026-03-10', '2026-01-05') 64 (days, d2 − d1) TIMESTAMPDIFF(unit, t1, t2)
TIMESTAMPDIFF(MINUTE, '2026-02-05 14:20', '2026-02-06 09:00') TIMEDIFF(t2, t1) TIMEDIFF('10:30:00', '09:00:00') DATE_FORMAT(d, fmt) DATE_FORMAT('2026-03-10', '%d %b %Y') STR_TO_DATE(s, fmt) STR_TO_DATE('10/03/2026', '%d/%m/%Y')
UNIX_TIMESTAMP(dt) / FROM_UNIXTIME(n) FROM_UNIXTIME(0) (session TZ UTC) CONVERT_TZ(dt, from, to)
CONVERT_TZ('2026-03-10 18:30', '+00:00', '+05:30') Common format specifiers: %Y year, %m month 01–12, %d day, %H hour 00–23, %i minutes, %s seconds, %f microseconds, %b short month name, %W weekday name.
Named time zones ('Asia/Kolkata') in CONVERT_TZ need the time-zone tables loaded (mysql_tzinfo_to_sql); numeric offsets always work.
Years of service as of 2026-09-29:
10.4 Control-flow and NULL functions IF(cond, a, b) a if cond is TRUE, else b IF(stock = 0, 'OUT', 'IN') IFNULL(a, b) a unless NULL, then b IFNULL(email, 'n/a') COALESCE(a, b,...) First non-NULL (standard) COALESCE(mobile, work_phone, 'none') NULLIF(a, b) price / NULLIF(stock, 0) CASE... END Standard conditional expression
1 if a is NULL, else 0 (one argument in MySQL) 10.5 Conversion functions
MySQL CAST targets: BINARY, CHAR[(n)], DATE, DATETIME, TIME, DECIMAL(p,s), SIGNED, UNSIGNED, JSON, FLOAT/DOUBLE (8.0.17+), YEAR (8.0.22+). There is no CAST(x AS INT); use SIGNED.
Implicit conversion warning: MySQL converts strings to numbers leniently: SELECT '12abc' + 1; returns 13 with a warning, and WHERE varchar_col = 123 compares numerically, which prevents index use and can match '123abc'. Always compare strings with strings.
10.6 Information functions
SELECT CONCAT(UPPER(last_name), ', ', first_name) AS display_name,
SUBSTRING_INDEX(email, '@', 1) AS mailbox,
CHAR_LENGTH(first_name) AS name_len,
CONCAT(LEFT(first_name, 1), LEFT(last_name, 1)) AS initials
FROM employees
WHERE dept_id = 1
ORDER BY emp_id;+----------------+--------------+----------+----------+
| display_name | mailbox | name_len | initials |
+----------------+--------------+----------+----------+
| RAO, Asha | asha.rao | 4 | AR |
| SHAH, Vikram | vikram.shah | 6 | VS |
| IYER, Neha | neha.iyer | 4 | NI |
| PILLAI, Meera | meera.pillai | 5 | MP |
+----------------+--------------+----------+----------+SELECT ROUND(CONV('0FA0', 16, 10) * 0.1 + 0, 1) AS pack_voltage_v; -- 4000 * 0.1 = 400.0SELECT first_name, hire_date,
TIMESTAMPDIFF(YEAR, hire_date, '2026-09-29') AS years_of_service
FROM employees
ORDER BY hire_date;+------------+------------+------------------+
| first_name | hire_date | years_of_service |
+------------+------------+------------------+
| Asha | 2015-03-01 | 11 |
| Rahul | 2017-09-01 | 9 |
| Vikram | 2018-06-15 | 8 |
| Arjun | 2019-11-05 | 6 |
| Neha | 2021-01-10 | 5 |
| Priya | 2022-04-20 | 4 |
| Meera | 2022-07-18 | 4 |
| Kiran | 2023-02-01 | 3 |
+------------+------------+------------------+SELECT first_name, salary,
CASE
WHEN salary >= 150000 THEN 'Band A'
WHEN salary >= 90000 THEN 'Band B'
ELSE 'Band C'
END AS band,
IF(dept_id IS NULL, 'Unassigned', 'Assigned') AS dept_status
FROM employees
ORDER BY emp_id;+------------+-----------+--------+-------------+
| first_name | salary | band | dept_status |
+------------+-----------+--------+-------------+
| Asha | 250000.00 | Band A | Assigned |
| Vikram | 150000.00 | Band A | Assigned |
| Neha | 95000.00 | Band B | Assigned |
| Rahul | 120000.00 | Band B | Assigned |
| Priya | 60000.00 | Band C | Assigned |
| Arjun | 90000.00 | Band B | Assigned |
| Kiran | 80000.00 | Band C | Unassigned |
| Meera | 95000.00 | Band B | Assigned |
+------------+-----------+--------+-------------+SELECT CAST('2026-09-29' AS DATE),
CAST(price AS UNSIGNED) FROM products LIMIT 1; -- integer cast (rounds DECIMAL in MySQL)
SELECT CAST('42' AS SIGNED) + 1; -- 43
SELECT CONVERT('abc' USING utf8mb4); -- charset conversion
SELECT CAST(12.5 AS DECIMAL(10,2)), CAST(3.7 AS CHAR);SELECT DATABASE(), USER(), CURRENT_USER(), VERSION(), CONNECTION_ID(), LAST_INSERT_ID(), ROW_COUNT(), FOUND_ROWS();
SELECT UUID(), UUID_SHORT();
SELECT SLEEP(1); -- pause (testing only)
SELECT BENCHMARK(1000000, SHA2('x', 256)); -- measure expression speedExpected Result
SELECT order_id,
DATE_FORMAT(order_date, '%b %d, %Y') AS order_day,
DATEDIFF('2026-03-31', order_date) AS age_days,
IF(status = 'CANCELLED', 0, total_amount) AS billable
FROM orders
ORDER BY order_id;+----------+--------------+----------+----------+
| order_id | order_day | age_days | billable |
+----------+--------------+----------+----------+
| 1001 | Jan 05, 2026 | 85 | 75800.00 |
| 1002 | Jan 18, 2026 | 72 | 12000.00 |
| 1003 | Feb 02, 2026 | 57 | 18100.00 |
| 1004 | Feb 14, 2026 | 45 | 0.00 |
| 1005 | Mar 01, 2026 | 30 | 1600.00 |
| 1006 | Mar 10, 2026 | 21 | 93000.00 |
+----------+--------------+----------+----------+Common Mistakes
LENGTH instead of CHAR_LENGTH for multibyte text.
CONCAT returning NULL because one argument is NULL (use CONCAT_WS or IFNULL).
ISNULL(a, b) (SQL Server habit) — MySQL's ISNULL takes one argument.
FORMAT() output used in calculations (it is a string with commas).
DATEDIFF argument order (end, start) and TIMESTAMPDIFF order (unit, start, end).
Functions on indexed columns in WHERE (WHERE YEAR(order_date) = 2026) — non-sargable.
Comparing VARCHAR columns to numbers.
Best Practices
Prefer standard functions (COALESCE, CASE, CAST) for portability; use MySQL-specific ones deliberately.
Keep indexed columns bare in WHERE; move arithmetic to constants.
Format dates and numbers at the presentation layer when possible.
Store times in UTC; convert with CONVERT_TZ for display.
Interview Relevance
High: "IFNULL vs COALESCE?", "LENGTH vs CHAR_LENGTH?", "DATEDIFF vs TIMESTAMPDIFF?", "NOW() vs SYSDATE()?", "How do you extract the domain from an email in MySQL?".
Practice Questions
Show each customer's email domain, or 'MISSING' if NULL.
Show products with price rounded up to the nearest thousand.
Show the month name and ISO week of each order.
Convert the CAN ID 0x2F0 to decimal and back to hex.
Classify products as Budget (< 1000), Mid (1000–20000), or Premium (> 20000).