当前位置: 首页 > news >正文

MySQL中的字符串函数

目录

一、字符串【分割】函数:SUBSTRING_INDEX()

SUBSTRING_INDEX函数

练习题

统计每种性别的人数

提取博客URL中的用户名

截取出年龄

SQL83 商品id数据清洗统计

SQL250 查找字符串中逗号出现的次数

二、字符串【截取】函数:SUBSTRING()

基本语法

参数说明

使用示例

示例数据

示例1:从指定位置开始截取

示例2:指定截取长度

示例3:从字符串末尾开始截取(使用负数位置)

示例4:结合其他字符串函数使用

示例5:处理可能不存在的分隔符

注意事项

三、正则表达式函数:REGEXP_SUBSTR()

1、基本语法

2、参数说明

3、核心功能

4、使用示例

示例数据

示例1:基本提取

示例2:指定匹配项序号

示例3:邮箱提取

示例4:使用捕获组

示例5:IP地址提取

5、匹配修饰符(match_type)

6、特殊注意事项

7、与类似函数对比

四、JSON函数

1、创建JSON值

2、查询JSON值

3、修改JSON值

4、JSON路径表达式

5、其他实用函数

6、实际应用示例

五、字符串搜索和位置定位:LOCATE()

基本语法

参数说明

返回值

使用示例

示例数据

示例1:基本查找

示例2:指定起始位置

示例3:与SUBSTRING结合使用

示例4:处理找不到的情况

示例5:INSTR函数(参数顺序不同)

注意事项


一、字符串【分割】函数:SUBSTRING_INDEX()

MySQL本身没有内置的SPLIT()函数,但可以通过其他方式实现字符串分割功能。

SUBSTRING_INDEX函数

SUBSTRING_INDEX()是MySQL中最常用的字符串分割函数,它可以根据指定的分隔符从字符串中提取子串,语法如下:

SUBSTRING_INDEX(str, delim, count)
  • 含义:返回字符串 str 中按分隔符 delim 分割后的第 count 个子串
  • str: 要分割的字符串
  • delim: 分隔符(可以是单个字符或多个字符)
  • count:
    • 正数:返回从左边开始第count个分隔符之前的所有内容
    • 负数:返回从右边开始第count个分隔符之后的所有内容

1、基本用法

-- 获取第一个逗号前的内容
SELECT SUBSTRING_INDEX('apple,banana,orange', ',', 1); 
-- 结果: 'apple'-- 获取最后一个逗号后的内容
SELECT SUBSTRING_INDEX('apple,banana,orange', ',', -1); 
-- 结果: 'orange'-- 获取前两个元素
SELECT SUBSTRING_INDEX('apple,banana,orange', ',', 1) AS item1,SUBSTRING_INDEX(SUBSTRING_INDEX('apple,banana,orange', ',', 2), ',', -1) AS item2;
-- 结果: item1='apple', item2='banana'

2. 处理多字符分隔符

-- 使用多字符作为分隔符
SELECT SUBSTRING_INDEX('apple||banana||orange', '||', 2);
-- 结果: 'apple||banana'SELECT SUBSTRING_INDEX('apple||banana||orange', '||', -1);
-- 结果: 'orange'
  • 找到第一个 || 在 apple||banana||orange 的 apple 之后,此时已找到1次分隔符
  • 找到第二个 || 在 banana 之后,此时已找到2次分隔符(达到count值)
  • 函数返回从开头到第二个 || 之前的所有内容:‘apple||banana’

3. 边界情况处理

-- 分隔符不存在时返回原字符串
SELECT SUBSTRING_INDEX('apple_banana_orange', ',', 1);
-- 结果: 'apple_banana_orange'-- count超过实际分隔数时返回整个字符串
SELECT SUBSTRING_INDEX('apple,banana', ',', 5);
-- 结果: 'apple,banana'-- 空字符串处理
SELECT SUBSTRING_INDEX('', ',', 1);
-- 结果: ''

注意:对于复杂的字符串分割需求,建议在应用层处理(如Python、Java等),或者在数据库设计时就避免使用分隔符存储多个值(遵循第一范式!!!!!!!!!!!!!)


练习题

统计每种性别的人数

selectSUBSTRING_INDEX (profile, ',', -1) as gender,count(*) as number
fromuser_submit 
group bygender

提取博客URL中的用户名

selectdevice_id,substring_index (blog_url, "/", -1) as user_name
fromuser_submit

截取出年龄

selectsubstring_index (substring_index (profile, ",", 3), ",", -1) as age,count(*) as number
fromuser_submit
group byage

SQL83 商品id数据清洗统计

select# SUBSTRING_INDEX (order_id, '_', -1) as product_id,regexp_substr(order_id,'p[0-9]+$') as product_id,count(*) as cnt
from order_log
group by product_id
order by cnt desc,product_id asc;
  • ‘p[0-9]+$’: 正则表达式模式
  • p: 匹配字母 “p”
  • [0-9]+: 匹配一个或多个数字(0-9)
  • $: 匹配字符串的结尾

SQL250 查找字符串中逗号出现的次数

SELECTid,LENGTH(string) - LENGTH(REPLACE(string, ',', '')) AS cnt
FROMstrings;

核心思路:

1.计算原始字符串的长度

2.计算去掉所有逗号后的字符串长度

3.两者相减就是逗号的数量

因为每个逗号占一个字符长度,去掉一个逗号会使字符串长度减少1,所以差值就是逗号的数量。


二、字符串【截取】函数:SUBSTRING()

参考: SQL中字符串截取函数(SUBSTRING)

SUBSTRING() 是 MySQL 中用于截取字符串的函数(SUBSTR() 是其别名,功能完全相同)。

基本语法

SUBSTRING(string, start [, length])
SUBSTR(string, start [, length])

参数说明

  1. string​:要截取的原始字符串(可以是字段名或字符串字面量)
  2. start​:开始截取的位置(整数)
    • 如果为正数,表示从字符串左侧开始计算的位置(从1开始)
    • 如果为负数,表示从字符串右侧开始计算的位置(从-1开始)
  3. length​(可选):要截取的字符数。如果省略,则截取从开始位置到字符串末尾的所有字符

使用示例

示例数据

假设有一个表 users 包含以下数据:

CREATE TABLE users (id INT,username VARCHAR(50)
);INSERT INTO users VALUES 
(1, 'john_doe'),
(2, 'jane_smith'),
(3, 'bob123');

示例1:从指定位置开始截取

-- 从第3个字符开始截取(包含第3个字符)
SELECT username, SUBSTRING(username, 3) FROM users;

结果:

john_doe   => hn_doe
jane_smith => ne_smith
bob123     => b123

示例2:指定截取长度

-- 从第2个字符开始截取3个字符
SELECT username, SUBSTRING(username, 2, 3) FROM users;

结果:

john_doe   => ohn
jane_smith => ane
bob123     => ob1

示例3:从字符串末尾开始截取(使用负数位置)

-- 从倒数第3个字符开始截取
SELECT username, SUBSTRING(username, -3) FROM users;

结果:

john_doe   => doe
jane_smith => ith
bob123     => 123

示例4:结合其他字符串函数使用

-- 提取电子邮件域名(从@符号后开始截取)
SELECT email, SUBSTRING(email, LOCATE('@', email) + 1) AS domain 
FROM customers;

LOCATE()后文有介绍

示例5:处理可能不存在的分隔符

-- 安全提取域名,当没有@符号时返回NULL
SELECT email, CASE WHEN LOCATE('@', email) > 0 THEN SUBSTRING(email, LOCATE('@', email) + 1)ELSE NULLEND AS domain
FROM customers;

注意事项

  1. 如果 start 为0,MySQL 5.6+ 会返回空字符串,而早期版本可能返回整个字符串
  2. 如果 start 超出字符串长度,返回空字符串
  3. 如果 length 为负数,会被视为0,返回空字符串
  4. 对于多字节字符(如中文),每个字符仍计为1个位置

三、正则表达式函数:REGEXP_SUBSTR()

REGEXP_SUBSTR() 是 MySQL 中用于通过正则表达式提取子字符串的强大函数(MySQL 8.0+ 版本支持)。

1、基本语法

REGEXP_SUBSTR(string, pattern [, position [, occurrence [, match_type]]])

2、参数说明

参数说明
string要搜索的原始字符串
pattern正则表达式模式
position (可选)开始搜索的位置(默认1)
occurrence (可选)要返回的匹配项序号(默认1)
match_type (可选)匹配修饰符(如'i'忽略大小写)

3、核心功能

从字符串中提取第一个匹配正则表达式的子字符串(除非指定occurrence)

4、使用示例

示例数据

CREATE TABLE sample_texts (id INT AUTO_INCREMENT PRIMARY KEY,content TEXT
);INSERT INTO sample_texts (content) VALUES 
('联系电话:010-12345678,备用:020-87654321'),
('邮箱:user@example.com 和 admin@test.org'),
('订单号:ORD20230515-1234 总价:$299.99'),
('IPv4地址:192.168.1.1,MAC地址:00:1A:2B:3C:4D:5E');

示例1:基本提取

-- 提取第一个电话号码
SELECT content,REGEXP_SUBSTR(content, '[0-9]{3,4}-[0-9]{7,8}') AS phone
FROM sample_texts
WHERE id = 1;

结果:

+-----------------------------------------------+--------------+
| content                                       | phone        |
+-----------------------------------------------+--------------+
| 联系电话:010-12345678,备用:020-87654321   | 010-12345678 |
+-----------------------------------------------+--------------+

示例2:指定匹配项序号

-- 提取第二个电话号码
SELECT content,REGEXP_SUBSTR(content, '[0-9]{3,4}-[0-9]{7,8}', 1, 2) AS backup_phone
FROM sample_texts
WHERE id = 1;

结果:

+-----------------------------------------------+--------------+
| content                                       | backup_phone |
+-----------------------------------------------+--------------+
| 联系电话:010-12345678,备用:020-87654321   | 020-87654321 |
+-----------------------------------------------+--------------+

示例3:邮箱提取

-- 提取所有邮箱地址
SELECT id,REGEXP_SUBSTR(content, '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}') AS email
FROM sample_texts
WHERE content REGEXP '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}';

结果:

+----+-------------------+
| id | email             |
+----+-------------------+
| 2  | user@example.com  |
| 2  | admin@test.org    |
+----+-------------------+

示例4:使用捕获组

-- 提取订单号中的日期部分
SELECT content,REGEXP_SUBSTR(content, 'ORD([0-9]{8})', 1, 1, '', 1) AS order_date
FROM sample_texts
WHERE id = 3;

结果:

+---------------------------------------+------------+
| content                               | order_date |
+---------------------------------------+------------+
| 订单号:ORD20230515-1234 总价:$299.99 | 20230515   |
+---------------------------------------+------------+

示例5:IP地址提取

-- 提取IP地址的第三个八位组
SELECT content,REGEXP_SUBSTR(content, '([0-9]{1,3}\\.){2}([0-9]{1,3})', 1, 1, '', 2) AS ip_third_octet
FROM sample_texts
WHERE id = 4;

结果:

+-------------------------------------------------+---------------+
| content                                         | ip_third_octet|
+-------------------------------------------------+---------------+
| IPv4地址:192.168.1.1,MAC地址:00:1A:2B:3C:4D:5E | 1             |
+-------------------------------------------------+---------------+

5、匹配修饰符(match_type)

修饰符作用
i不区分大小写
c区分大小写
m多行模式
n允许.匹配换行符
uUnix换行符

示例:

-- 不区分大小写匹配
SELECT REGEXP_SUBSTR('Hello World', 'woRLd', 1, 1, 'i') AS match_result;
-- 返回 'World'

6、特殊注意事项

  1. 性能影响​:复杂正则表达式可能影响查询性能
  2. 版本要求​:MySQL 8.0+ 完整支持
  3. 字符编码​:确保正则表达式与字符串编码兼容
  4. 转义处理​:在SQL字符串中需要双重转义(\\d 表示 \d

7、与类似函数对比

函数特点
SUBSTRING()简单位置截取
LOCATE()子字符串位置查找
REGEXP_SUBSTR()基于正则的灵活提取
REGEXP_REPLACE()正则替换

四、JSON函数

MySQL 从5.7版本开始支持JSON数据类型,并提供了一系列强大的JSON处理函数。

1、创建JSON值

  1. JSON_OBJECT()​​ - 创建JSON对象

    SELECT JSON_OBJECT('name', '张三', 'age', 25, 'is_student', TRUE);
    -- 结果: {"name": "张三", "age": 25, "is_student": true}
  2. JSON_ARRAY()​​ - 创建JSON数组

    SELECT JSON_ARRAY(1, 'abc', NULL, TRUE, JSON_OBJECT('key', 'value'));
    -- 结果: [1, "abc", null, true, {"key": "value"}]

2、查询JSON值

  1. JSON_EXTRACT() / ->​​ - 提取JSON数据

    SELECT JSON_EXTRACT('{"name": "李四", "age": 30}', '$.name');
    -- 或使用 -> 操作符
    SELECT JSON_OBJECT('name', '王五') -> '$.name';
    -- 结果: "王五"
  2. ​->>​​ - 提取并取消引号

    SELECT JSON_OBJECT('name', '赵六') ->> '$.name';
    -- 结果: 赵六 (不带引号的字符串)
  3. JSON_CONTAINS()​​ - 检查是否包含特定值

    SELECT JSON_CONTAINS('[1, 2, 3]', '2', '$');
    -- 结果: 1 (true)

3、修改JSON值

  1. JSON_SET()​​ - 设置值(存在则更新,不存在则添加)

    SELECT JSON_SET('{"a": 1}', '$.a', 10, '$.b', 2);
    -- 结果: {"a": 10, "b": 2}
  2. JSON_INSERT()​​ - 仅添加新值

    SELECT JSON_INSERT('{"a": 1}', '$.a', 10, '$.b', 2);
    -- 结果: {"a": 1, "b": 2} (a未被更新)
  3. JSON_REPLACE()​​ - 仅更新现有值

    SELECT JSON_REPLACE('{"a": 1, "b": 2}', '$.a', 10, '$.c', 3);
    -- 结果: {"a": 10, "b": 2} (c未被添加)
  4. JSON_REMOVE()​​ - 删除元素

    SELECT JSON_REMOVE('{"a": 1, "b": 2}', '$.a');
    -- 结果: {"b": 2}

4、JSON路径表达式

路径表达式用于定位JSON文档中的特定部分:

  • $ 表示文档根
  • $.key 表示对象中的键
  • $[n] 表示数组中的第n个元素(从0开始)
  • $[*] 表示数组中的所有元素
  • $.key1.key2 表示嵌套对象

5、其他实用函数

  1. JSON_TYPE()​​ - 返回JSON值的类型

    SELECT JSON_TYPE('{"a": 1}'); -- OBJECT
    SELECT JSON_TYPE('[1, 2]');   -- ARRAY
  2. JSON_LENGTH()​​ - 返回JSON文档长度

    SELECT JSON_LENGTH('[1, 2, {"a": 3}]'); -- 3
  3. JSON_KEYS()​​ - 返回对象的所有键

    SELECT JSON_KEYS('{"a": 1, "b": 2}'); -- ["a", "b"]
  4. JSON_SEARCH()​​ - 搜索值并返回路径

    SELECT JSON_SEARCH('{"a": 1, "b": "value"}', 'one', 'value');
    -- 结果: "$.b"

6、实际应用示例

-- 创建包含JSON列的表
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50),profile JSON
);-- 插入JSON数据
INSERT INTO users (name, profile) VALUES 
('张三', '{"age": 25, "hobbies": ["篮球", "音乐"], "address": {"city": "北京"}}');-- 查询JSON字段
SELECT name, profile->>'$.address.city' AS city FROM users;-- 更新JSON字段
UPDATE users 
SET profile = JSON_SET(profile, '$.age', 26, '$.hobbies[2]', '阅读')
WHERE name = '张三';-- 使用JSON条件查询
SELECT name FROM users 
WHERE JSON_CONTAINS(profile->'$.hobbies', '"篮球"');

五、字符串搜索和位置定位:LOCATE()

LOCATE() 是 MySQL 中用于查找子字符串位置的函数INSTR() 是它的变体,功能类似但参数顺序不同)。

基本语法

LOCATE(substring, string [, start])

参数说明

  1. substring​:要查找的子字符串
  2. string​:被搜索的原始字符串
  3. start​(可选):开始搜索的位置(从1开始计数),如果省略则从字符串开头搜索

返回值

  • 返回子字符串第一次出现的位置(从1开始计数)
  • 如果找不到则返回0
  • 如果任一参数为NULL则返回NULL

使用示例

示例数据

使用之前的 users 表:

SELECT * FROM users;

结果:

+----+------------+
| id | username   |
+----+------------+
| 1  | john_doe   |
| 2  | jane_smith |
| 3  | bob123     |
+----+------------+

示例1:基本查找

-- 查找下划线位置
SELECT username, LOCATE('_', username) AS underscore_pos FROM users;

结果:

+------------+----------------+
| username   | underscore_pos |
+------------+----------------+
| john_doe   | 5              |
| jane_smith | 5              |
| bob123     | 0              |
+------------+----------------+

示例2:指定起始位置

-- 从第6个字符开始查找字母'e'
SELECT username, LOCATE('e', username, 6) AS e_pos FROM users;

结果:

+------------+-------+
| username   | e_pos |
+------------+-------+
| john_doe   | 8     | -- 'doe'中的e
| jane_smith | 0     | -- 从第6位'smith'中没有e
| bob123     | 0     |
+------------+-------+

示例3:与SUBSTRING结合使用

-- 提取下划线后的部分
SELECT username, SUBSTRING(username, LOCATE('_', username) + 1) AS after_underscore
FROM users;

结果:

+------------+------------------+
| username   | after_underscore |
+------------+------------------+
| john_doe   | doe              |
| jane_smith | smith            |
| bob123     | bob123           | -- 没有下划线,返回整个字符串
+------------+------------------+

示例4:处理找不到的情况

-- 安全提取下划线后的部分(找不到时返回NULL)
SELECT username,CASE WHEN LOCATE('_', username) > 0 THEN SUBSTRING(username, LOCATE('_', username) + 1)ELSE NULLEND AS after_underscore
FROM users;

示例5:INSTR函数(参数顺序不同)

-- INSTR(string, substring) 是 LOCATE(substring, string) 的变体
SELECT username, INSTR(username, '_') AS underscore_pos FROM users;

注意事项

  1. 搜索是区分大小写的,除非使用不区分大小写的排序规则
  2. 对于多字节字符(如中文),每个字符计为1个位置
  3. 如果 start 小于1,会被视为1
  4. 如果 start 大于字符串长度,返回0
  5. 空字符串 '' 作为子字符串时,在有效位置范围内会返回 start 参数值
http://www.dtcms.com/a/333039.html

相关文章:

  • PowerShell 格式化系统完全掌握(下):自定义列/格式字符串/对齐与宽度 + 实战模板
  • 抗日胜利80周年 | HTML页面
  • 智和信通全栈式运维平台落地深圳某学院,赋能运维管理提质提效
  • TCP传输层协议(4)
  • 微信实名认证组件
  • 二十四、Mybatis-基础操作-删除(预编译SQL)
  • SAP ALV导出excel 报 XML 错误的 /xl/sharedStrings.xml
  • Android协程的用法大全
  • 汽车电子:现代汽车的智能核心
  • Unity_数据持久化_Json
  • 使用原生css实现word目录样式,标题后面的...动态长度并始终在标题后方(生成点线)
  • 第七十章:告别“手写循环”噩梦!Trainer结构搭建:PyTorch Lightning让你“一键炼丹”!
  • Codeforces Deque工艺
  • 用 FreeMarker 动态构造 SQL 实现数据透视分析
  • STM32学习笔记12-串口数据包收发FlyMcuST-LINK Utility
  • Shortest Routes II(Floyd最短路)
  • 管家婆辉煌系列试用版/期限说明
  • Shader开发(十三)理解片元插值
  • 淘米自动签到脚本
  • 大气负氧离子自动监测站:解密空气的科技密码
  • 有红帽认证证书可以0元置换华为openEuler-HCIA/HCIP认证
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|13th Aug. , 2025
  • MyBatis StatementHandler核心原理详解
  • Nginx反向代理Tomcat实战指南
  • mysql-DDLy语句案例
  • 基于asp.net#C##VUE框架的独居老人物资配送系统的设计与实现#sql server#visual studio
  • OpenZeppelin Contracts 架构分层分析
  • 基于机器学习的赌博网站识别系统设计与实现
  • 【计算机视觉与深度学习实战】02基于形态学的权重自适应图像去噪系统
  • 【车联网kafka】常用参数及其命令总结(第八篇)