MySQL 8.0+推荐用REGEXP_REPLACE配合]*>|||一次性清除HTML标签、注释、服务端指令和CDATA,但需注意不支持多行模式,换行需预处理。

MySQL 8.0+ 直接用 REGEXP_REPLACE 去 HTML 标签最省事
如果你用的是 MySQL 8.0 或更高版本,REGEXP_REPLACE 是最快捷、最可控的方式。它能一次性剥离成对标签(如 <p></p>)、自闭合标签(如 <br>)、带属性的标签(如 <div class="x">),甚至注释和 CDATA。<p>常见错误是只匹配 <code>]*> —— 这会漏掉换行、注释里的 <!-- ... -->,还可能误杀文本中合法的 符号(比如 “5 <p>推荐写法:</p><pre class="brush:php;toolbar:false;">SELECT REGEXP_REPLACE(html_content, '<[^>]*>|<!--.*?-->|<\?[^\?]*\?>|<\!\[CDATA\[.*?\]\]>', '') AS clean_text FROM articles;</pre><p>说明:</p>
<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>
<ul>
<li>
<code>]*>:覆盖大部分常规标签(含属性),但不跨行
<!--.*?-->:非贪婪匹配 HTML 注释(需开启 REGEXP_INSTR 的 g 模式或多次调用):处理 PHP/ASP 等服务端指令(如 <?php echo "x"; ?>):匹配 CDATA 区段注意:REGEXP_REPLACE 默认不支持多行模式(m 标志),所以如果 HTML 换行在标签中间(如 <div>),上面正则会失效 —— 此时必须先用 <code>REPLACE 清除换行,或改用存储函数预处理。
MySQL 5.7 及更早版本只能靠自定义函数 + 循环剥离
老版本没有正则替换能力,REPLACE 又无法应对任意标签结构,唯一可靠办法是写一个存储函数,用 LOCATE + SUBSTRING + INSERT 循环剔除每一对 <...></...>。
典型陷阱是忽略嵌套和重叠边界,比如 <b>hello <i>world</i></b> 处理不当会变成 hello <i>world</i>(漏掉外层闭合标签);更糟的是遇到 <script>alert('<div>');</script> 这类内容里含 的情况,纯字符串扫描会提前截断。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
实操建议:
- 函数里加最大循环次数限制(如 100 次),防无限循环
- 每次只删最内层成对标签(用
LOCATE('', ...)找最近闭合位置),比从左到右扫更安全 - 对已知字段(如富文本编辑器输出),可先
REPLACE(html, '<', ' 解码 HTML 实体,再处理 - 别忘了清理多余空白:
TRIM(REPLACE(REPLACE(clean_text, ' ', ''), ' ', ' '))
PostgreSQL 和 SQL Server 用户别硬套 MySQL 写法
PostgreSQL 有原生 regexp_replace(),且默认支持 g(全局)和 n(点号匹配换行)标志,直接写 regexp_replace(html, ']*>|<!--.*?-->', '', 'gn') 就行;SQL Server 2017+ 可用 STRING_SPLIT + FOR XML 组合模拟,但更推荐在应用层处理 —— 因为 T-SQL 的字符串函数缺乏非贪婪匹配,写出来的逻辑极易出错。
关键差异点:
- MySQL 的
REGEXP_REPLACE不支持g标志(8.0.22+ 才加),老版本要手动循环调用 - PostgreSQL 正则引擎更强大,
?非贪婪、(?s)单行模式都可用 - SQL Server 的
PATINDEX('%]%>%', ...)只能找第一个,没法递归
真正上线前必须验证的三类边界场景
很多团队测试只用简单 <p>abc</p>,结果上线后崩在真实数据上。以下三类必须覆盖:
- 含 JS/CSS 的混合内容:
<script>var x = "<div>";</script><p>text</p>—— 正则若没排除 script/style 标签内部,会把"<div>" 当标签删掉<li>实体编码:<code><span>hello</span>应保留原样,不是 HTML 标签;但<b>bold</b>显示为<b>bold</b>,是否需要二次解码得看业务 - 超长字段(> 1MB):MySQL 函数有
max_sp_recursion_depth限制,循环函数可能中途报错;PostgreSQL 则要注意work_mem是否够用
最易被忽略的是字符集问题:如果字段是 utf8mb4,但正则表达式里用了 ASCII 范围的 [^>],某些 emoji 或生僻字可能被意外截断 —— 测试时务必用真实生产数据抽样跑一遍。


















