如何在存储过程的内连接等于条件中改用正则匹配实现特定模式匹配
解决方案:修改内连接条件实现占位符匹配
这问题挺有意思的,要实现你需要的匹配规则,核心思路是把ET.Value里的<...>占位符和A.Value里的{...}占位符统一替换成同一个标记,然后比较处理后的字符串是否完全一致——这样既保留了完全相等的匹配场景,也能让对应位置的占位符互相匹配。
下面分不同数据库环境给出具体的修改方案:
1. 支持正则替换的数据库(SQL Server 2017+/MySQL 8.0+/PostgreSQL)
这类数据库原生支持正则表达式替换,可以直接用REGEXP_REPLACE函数处理字符串:
SQL Server 2017+ 写法
修改最后一个内连接的ON子句为:
ON REGEXP_REPLACE(ET.Value, '<.*?>', '#PLACEHOLDER#') = REGEXP_REPLACE(A.Value, '\{.*?\}', '#PLACEHOLDER#')
- 解释:
REGEXP_REPLACE(ET.Value, '<.*?>', '#PLACEHOLDER#'):把ET.Value中所有<开头、>结尾的最短匹配(非贪婪模式,避免误匹配多个占位符)替换成统一标记#PLACEHOLDER#REGEXP_REPLACE(A.Value, '\{.*?\}', '#PLACEHOLDER#'):把A.Value中所有{开头、}结尾的最短匹配替换成同一个标记(注意{在正则里是特殊字符,需要用\{转义)
MySQL 8.0+ 写法
MySQL中转义字符需要额外处理,写法如下:
ON REGEXP_REPLACE(ET.Value, '<.*?>', '#PLACEHOLDER#') = REGEXP_REPLACE(A.Value, '\\{.*?\\}', '#PLACEHOLDER#')
PostgreSQL 写法
PostgreSQL的REGEXP_REPLACE默认只替换第一个匹配,需要加'g'参数开启全局替换:
ON REGEXP_REPLACE(ET.Value, '<.*?>', '#PLACEHOLDER#', 'g') = REGEXP_REPLACE(A.Value, '\{.*?\}', '#PLACEHOLDER#', 'g')
2. 不支持正则替换的数据库(比如SQL Server 2016及更早版本)
如果你的数据库不支持正则,可以通过自定义字符串替换函数来实现:
第一步:创建自定义替换函数
-- 替换ET.Value中的<...>占位符 CREATE FUNCTION dbo.ReplaceAngleBrackets(@input NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN DECLARE @start INT, @end INT SET @start = CHARINDEX('<', @input) WHILE @start > 0 BEGIN SET @end = CHARINDEX('>', @input, @start) IF @end = 0 BREAK -- 如果只有<没有>,停止处理 SET @input = STUFF(@input, @start, @end - @start + 1, '#PLACEHOLDER#') SET @start = CHARINDEX('<', @input) END RETURN @input END -- 替换A.Value中的{...}占位符 CREATE FUNCTION dbo.ReplaceCurlyBrackets(@input NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN DECLARE @start INT, @end INT SET @start = CHARINDEX('{', @input) WHILE @start > 0 BEGIN SET @end = CHARINDEX('}', @input, @start) IF @end = 0 BREAK -- 如果只有{没有},停止处理 SET @input = STUFF(@input, @start, @end - @start + 1, '#PLACEHOLDER#') SET @start = CHARINDEX('{', @input) END RETURN @input END
第二步:修改内连接条件
ON dbo.ReplaceAngleBrackets(ET.Value) = dbo.ReplaceCurlyBrackets(A.Value)
验证你的示例场景
用上面的方案测试你给出的例子:
- ✅ ET.Value='HI'且A.Value='HI':处理后都是
HI,匹配成功 - ✅ ET.Value='SOME\THING\RIGHT<ABC>\THERE'且A.Value='SOME\THING\RIGHT{DEFGHILMNOP}\THERE':处理后都是
SOME\THING\RIGHT\#PLACEHOLDER#\THERE,匹配成功 - ✅ ET.Value='HOME\SWEET\HOME<12345>'且A.Value='HOME\SWEET\HOME{4875928346}':处理后都是
HOME\SWEET\HOME\#PLACEHOLDER#\,匹配成功 - ❌ ET.Value='EXAMPLE<1234>'且A.Value='EG{1234}':处理后分别是
EXAMPLE#PLACEHOLDER#和EG#PLACEHOLDER#,不相等,匹配失败 - ❌ ET.Value='dog'且A.Value='cat':处理后还是原字符串,不相等,匹配失败
完全符合你需要的规则~
内容的提问来源于stack exchange,提问作者rlnnclt
相关产品推荐
相关产品推荐

