讲解

除了聚合函数,SQL 还有大量对单行值做处理的标量函数。字符串一族:UPPER/LOWER 转大小写、LENGTH 求长度、SUBSTR(s, 起点, 长度) 截取(SQL 的下标从 1 开始!)、REPLACE 替换、TRIM 去两端空白,拼接用 || 运算符(标准 SQL 写法)。数值一族:ROUND(x, n) 四舍五入到 n 位小数、ABS 绝对值、% 取余。空值处理就是之前学过的 COALESCE。

日期时间函数是方言差异的重灾区。SQLite 里 DATE('now') 取当前日期,strftime('%Y-%m', order_date) 从日期文本里提取年月,按月份统计订单就靠它;MySQL 用 DATE_FORMAT,PostgreSQL 用 TO_CHAR 或 date_trunc,参数格式全不一样。学标准思路、用的时候查手册,是面对日期函数的正确姿势。

再强调一次可移植性:字符串拼接 MySQL 用 CONCAT() 函数而标准用 ||;分页 MySQL/PostgreSQL 用 LIMIT 而 SQL Server 用 TOP/OFFSET FETCH。本教程基于 SQLite,示例里的函数在 SQLite 都能跑,换数据库时先查对应方言。函数还可以嵌套组合:UPPER(SUBSTR(name, 1, 1)) 取姓名首字并转大写,从内往外读。

示例

字符串函数与拼接(注意 SQL 下标从 1 开始):

SELECT name, LENGTH(name) AS name_len, SUBSTR('2025-01-05', 1, 4) AS year_part, UPPER('sql') AS upper_text, TRIM('  你好  ') AS trimmed FROM students LIMIT 3;

SELECT title || '(' || category || ')' AS display FROM courses;

数值函数:平均客单价保留两位小数,金额与平均值的差:

SELECT ROUND(AVG(amount), 2) AS avg_amount FROM orders;

SELECT id, amount, ABS(amount - 58.67) AS diff FROM orders ORDER BY diff DESC LIMIT 3;

日期函数实战:按月份统计订单数和金额:

SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS order_count, SUM(amount) AS total FROM orders GROUP BY month ORDER BY month;

常见坑

  • SUBSTR 下标从 1 开始:从 0 开始数是很多程序员的本能,SUBSTR(title, 0, 3) 在 SQLite 里会少给你一个字符。SQL 世界普遍从 1 开始。
  • 以为 LENGTH 数的是字节:SQLite 的 LENGTH 对文本数字符数('你好' 是 2),但 MySQL 的 LENGTH 数字节('你好' 是 6),MySQL 里数字符要用 CHAR_LENGTH。跨库时先确认语义。
  • 直接套用别的库的日期函数:DATE_FORMAT、TO_CHAR、strftime 互不相通,照搬必报错。迁移 SQL 时把日期函数列为重点检查项。
  • 在 WHERE 里对列用函数导致索引失效:WHERE strftime('%Y', order_date) = '2025' 无法利用 order_date 上的普通索引。范围写法 WHERE order_date >= '2025-01-01' AND order_date < '2026-01-01' 对索引友好。

小结

字符串、数值、日期、空值四类标量函数覆盖日常处理;SUBSTR 下标从 1 开始,函数方言差异大,WHERE 里对列套函数会拖垮索引。下一节从读转向写:INSERT、UPDATE、DELETE。