EP08. "常用字符串函数速查(MySQL vs SQL Server)"
🔒 登录后可标记已读- 同一个「拼接字符串」需求,MySQL 和 SQL Server 语法长得几乎一样,但「取长度」这种最基本的操作,函数名却完全不同(LENGTH vs LEN),照抄别的数据库的语法会直接报错
- 涵盖 10 个字符串函数:拼接(CONCAT)、取长度、大小写转换、去空白(TRIM)、截取(SUBSTRING / LEFT / RIGHT)、替换(REPLACE)、补齐位数(LPAD)
- 例子沿用 EP01 / EP02 的 users / orders / products 电商场景
- 前置知识:先看过 EP01 的 SELECT 基本语法
重点内容
字符串函数速查表
| 用途 | MySQL | SQL Server | 例子 |
|---|---|---|---|
| 拼接字符串 | CONCAT(str1, str2, ...) | CONCAT(str1, str2, ...) | CONCAT(first_name, ' ', last_name) |
| 取字符串长度 | LENGTH(str) | LEN(str) | LENGTH(sku) |
| 转大写 | UPPER(str) | UPPER(str) | UPPER(name) |
| 转小写 | LOWER(str) | LOWER(str) | LOWER(email) |
| 去除头尾空白 | TRIM(str) | TRIM(str)(2017+) | TRIM(name) |
| 截取子字符串 | SUBSTRING(str, start, length) | SUBSTRING(str, start, length) | SUBSTRING(order_no, 5, 4) |
| 取左边 N 个字符 | LEFT(str, n) | LEFT(str, n) | LEFT(phone, 3) |
| 取右边 N 个字符 | RIGHT(str, n) | RIGHT(str, n) | RIGHT(sku, 4) |
| 替换内容 | REPLACE(str, old, new) | REPLACE(str, old, new) | REPLACE(description, 'OldBrand', 'NewBrand') |
| 左侧补齐位数 | LPAD(str, len, pad) | 无原生函数,需组合 RIGHT() + REPLICATE() | 见下方说明 |
拼接字符串:CONCAT
用户全名通常拆成 first_name / last_name 两个栏位存,显示时才拼起来:
-- MySQL / SQL Server 写法相同
SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM users
WHERE id = 1001;
-- 结果:Tan Ah Beng
📌 PostgreSQL 除了也有 CONCAT(),更常见的写法是用 || 运算符:first_name || ' ' || last_name,效果一样,是 PostgreSQL 特有的拼接语法。
取字符串长度:LENGTH vs LEN
产品 SKU 编码规定必须是 8 位,用长度函数抓出不符合规则的脏数据:
-- MySQL
SELECT sku FROM products WHERE LENGTH(sku) <> 8;
-- SQL Server
SELECT sku FROM products WHERE LEN(sku) <> 8;
📌 LENGTH()/LEN() 算出来的数字几乎都等于字符数,但 MySQL 官方定义是「字节数」——如果 sku 里混了中文字这类多字节字符,LENGTH() 数出来的数字会比实际字数大,这时候要改用 CHAR_LENGTH()。SQL Server 的 LEN() 本身就是数字符数,没有这个坑,但它会忽略结尾空白,前导空白照算。
大小写转换:UPPER / LOWER
搜索产品时不想管使用者输入大小写,统一转大写比对;email 入库前统一转小写,避免重复注册:
-- 产品名称统一转大写比对(两边语法相同)
SELECT * FROM products WHERE UPPER(name) = UPPER('iphone case');
-- email 入库前转小写,避免 Big@Gmail.com 和 big@gmail.com 被当成两个用户
UPDATE users SET email = LOWER(email) WHERE id = 1001;
去除头尾空白:TRIM
用户注册表单常常会不小心多打空格,入库前先 TRIM 掉:
-- MySQL
UPDATE users SET name = TRIM(name) WHERE id = 1001;
-- SQL Server(2017 之后才支持这个简化写法)
UPDATE users SET name = TRIM(name) WHERE id = 1001;
📌 SQL Server 2017 之前没有 TRIM(),只能用 LTRIM(RTRIM(name)) 两个函数叠起来用,维护旧系统时常会看到这种写法。
截取字符串:SUBSTRING / LEFT / RIGHT
订单编号格式是 ORD-2026-000123(品牌前缀-年份-流水号),要单独抓出年份或流水号:
-- 两边语法相同:从第 5 个字符开始,取 4 个字符 = 年份
SELECT order_no, SUBSTRING(order_no, 5, 4) AS order_year
FROM orders
WHERE id = 5001;
-- order_year = 2026
-- LEFT:抓电话号码的区号(假设固定前 3 位是区号)
SELECT phone, LEFT(phone, 3) AS area_code FROM users WHERE id = 1001;
-- RIGHT:抓 SKU 最后 4 位当校验码
SELECT sku, RIGHT(sku, 4) AS check_code FROM products WHERE id = 501;
替换内容:REPLACE
供应商换了新品牌名,旧的产品说明文字要批量替换:
-- 两边语法相同
UPDATE products
SET description = REPLACE(description, 'OldBrand', 'NewBrand')
WHERE description LIKE '%OldBrand%';
📌 MySQL 的 REPLACE() 区分大小写('OldBrand' 不会匹配到 'oldbrand'),SQL Server 的 REPLACE() 预设不分大小写(实际是不是分大小写取决于栏位的排序规则 collation,但默认安装通常是不分大小写)——同一段替换逻辑搬到不同数据库,结果可能不一样,要留意。
左侧补齐位数:LPAD
把订单流水号统一补成 6 位数字(88 → 000088),拼出固定长度的订单编号:
-- MySQL
SELECT LPAD(88, 6, '0') AS padded_seq;
-- 000088
-- SQL Server 没有原生 LPAD(),常见做法是用 RIGHT + REPLICATE 组合出来
SELECT RIGHT(REPLICATE('0', 6) + CAST(88 AS VARCHAR(6)), 6) AS padded_seq;
-- 000088
📌 PostgreSQL 反而跟 MySQL 语法一致,也有原生 LPAD(string, length, fill),SQL Server 是三个方言里唯一没有内建 LPAD 的。
常见错误
- ❌ 把 MySQL 的
LENGTH()直接搬到 SQL Server 用——SQL Server 要用LEN(),函数名不一样,写错会直接报「找不到此函数」 - ❌ 忘记 SQL Server 的 TRIM() 要 2017 以上版本才有——维护旧系统(SQL Server 2016 或更早)要改用
LTRIM(RTRIM(str)) - ❌ 以为 REPLACE() 在所有数据库都是大小写敏感——MySQL 默认区分大小写,SQL Server 默认通常不分,同一段逻辑换数据库结果可能不同,正式环境最好先实测
- 💡 需要「补齐固定位数」的编号(订单号、发票号常见),MySQL / PostgreSQL 直接用 LPAD();SQL Server 没有对应函数,要用
RIGHT(REPLICATE(...) + CAST(...), n)组合出来
Sources
Blog / Website: