PostgreSQL基于多分隔符正则提取名称的技术问询
搞定SQL中非原子name字段的清洗:提取单个主名称
嘿,刚接触SQL就碰到字段清洗的难题啦?别慌,我来一步步帮你解决这个问题!
先把需求拆清楚
你需要从name字段里提取单个主名称,要移除的内容包括:
- 括号及其内部的所有内容(比如旧ID、别名)
- 用逗号(
,)、分号(;)或者OR分隔的次要/三级名称
正则表达式思路(分两步走更稳妥)
咱们可以分两次处理,先搞定括号内容,再清理分隔后的次要名称,这样逻辑更清晰:
第一步:干掉括号及内部内容
正则表达式:\s*\(.*?\)\s*
\s*:匹配括号前后的任意空白(避免清理后留下多余空格)\(.*?\):非贪婪匹配括号及里面的所有内容(这样不会把多个括号的内容连起来匹配,比如A(B)C(D)只会分别去掉(B)和(D))
第二步:移除分隔符后的次要名称
正则表达式:\s*(?:,|;|\bOR\b)\s*.+$
\s*:匹配分隔符前后的空白(?:,|;|\bOR\b):匹配逗号、分号,或者独立的OR单词(\b是单词边界,防止误匹配比如ORDER里的OR).+$:匹配分隔符之后的所有内容直到行尾,直接删掉
结合SQL函数实现(主流数据库示例)
不同数据库的正则替换函数略有差异,给你列几个常用的:
MySQL/MariaDB
用REGEXP_REPLACE函数,把两步合并起来写:
SELECT REGEXP_REPLACE( REGEXP_REPLACE(name, '\\s*\\(.*?\\)\\s*', ''), -- 先清括号内容 '\\s*(?:,|;|\\bOR\\b)\\s*.+$', '' -- 再清次要名称 ) AS cleaned_name FROM your_table;
PostgreSQL
同样用REGEXP_REPLACE,这里反斜杠不需要额外转义:
SELECT REGEXP_REPLACE( REGEXP_REPLACE(name, '\s*\(.*?\)\s*', ''), '\s*(?:,|;|\bOR\b)\s*.+$', '' ) AS cleaned_name FROM your_table;
SQL Server(2017+版本)
SQL Server 2017及以后支持REGEXP_REPLACE,写法如下:
SELECT REGEXP_REPLACE( REGEXP_REPLACE(name, '\s*\(.*?\)\s*', ''), '\s*(?:,|;|\bOR\b)\s*.+$', '' ) AS cleaned_name FROM your_table;
可复现示例
假设你的name字段有这些原始值:
实际原始值:
- 苹果(红富士), 青苹果 OR 黄苹果
- 微软公司; Microsoft (旧ID:123)
- 特斯拉(TSLA) OR 特斯拉汽车
经过上面的SQL处理后,期望输出就是:
- 苹果
- 微软公司
- 特斯拉
小细节补充
- 如果
OR是大小写混合的(比如or/Or),可以加不区分大小写的规则:- MySQL:在正则末尾加
(?i),比如'\\s*(?:,|;|\\bOR\\b)\\s*.+$'(?i) - PostgreSQL:给
REGEXP_REPLACE加'gi'标志,比如REGEXP_REPLACE(..., '\s*(?:,|;|\bOR\b)\s*.+$', '', 'gi') - SQL Server:在正则开头加
(?i),比如'(?i)\\s*(?:,|;|\\bOR\\b)\\s*.+$'
- MySQL:在正则末尾加
- 如果遇到嵌套括号的复杂情况,非贪婪匹配可能不够用,但大部分业务场景下
\(.*?\)完全能应付。
内容的提问来源于stack exchange,提问作者philiporlando
相关产品推荐
相关产品推荐

