在日常的数据库开发工作中,我们经常遇到需要从混杂的字符串中提取特定类型字符的场景。比如从地址中提取中文、从订单号中提取数字、从用户输入中过滤出英文等。今天给大家分享一套实用的SQL Server自定义函数,帮助您轻松应对这些需求。
一、提取中文字符
函数:dbo.getCN
这个函数利用Unicode编码范围(19968-40869)来识别中文字符,支持繁简体中文。
CREATE FUNCTION dbo.getCN( @str AS NVARCHAR(4000))RETURNS NVARCHAR(4000)ASBEGIN DECLARE @word NCHAR(1), @CN NVARCHAR(4000) SET @CN = ''
WHILE LEN(@str) > 0 BEGIN SET @word = LEFT(@str, 1) IF UNICODE(@word) BETWEEN 19968 AND 19968 + 20901 SET @CN = @CN + @word SET @str = RIGHT(@str, LEN(@str) - 1) END
RETURN @CNENDGO
测试示例
PRINT dbo.getCN('ASDKG论坛KDL')
PRINT dbo.getCN('ASDKG論壇KDL')
PRINT dbo.getCN('ASDKDL')
二、提取数字
函数:dbo.getNumber
使用PATINDEX配合正则表达式模式,过滤掉所有非数字字符。
CREATE FUNCTION dbo.getNumber(@S VARCHAR(100))RETURNS VARCHAR(100)ASBEGIN WHILE PATINDEX('%[^0-9]%', @S) > 0 BEGIN SET @S = STUFF(@S, PATINDEX('%[^0-9]%', @S), 1, '') END RETURN @SENDGO
测试示例
PRINT dbo.getNumber('呵呵ABC123ABC')-- 结果:123
扩展技巧
如果需要保留逗号、星号等其他字符,可以在模式中添加:
PATINDEX('%[^0-9,*]%', @S) > 0
三、提取英文字符
函数:dbo.getEn
提取字符串中的大小写英文字母(a-z)。
CREATE FUNCTION dbo.getEn(@S VARCHAR(100))RETURNS VARCHAR(100)ASBEGIN WHILE PATINDEX('%[^a-z]%', @S) > 0 BEGIN SET @S = STUFF(@S, PATINDEX('%[^a-z]%', @S), 1, '') END RETURN @SENDGO
测试示例
PRINT dbo.getEn('呵呵ABC123ABC')-- 结果:ABCABC
四、提取简体中文
函数:dbo.getSimplifiedCN
通过"吖-座"这个汉字范围来匹配简体中文字符。
CREATE FUNCTION dbo.getSimplifiedCN(@S NVARCHAR(100))RETURNS VARCHAR(100)ASBEGIN WHILE PATINDEX('%[^吖-座]%', @S) > 0 SET @S = STUFF(@S, PATINDEX('%[^吖-座]%', @S), 1, N'') RETURN @SENDGO
测试示例
PRINT dbo.getSimplifiedCN('呵呵ABC123ABC')-- 结果:呵呵
五、过滤重复字符(带分隔符)
函数:dbo.distinct_str
适用于处理以特定分隔符连接的字符串,去重后保留原有顺序。
CREATE FUNCTION dbo.distinct_str(@S NVARCHAR(100), @SPLIT VARCHAR(50))RETURNS VARCHAR(100)ASBEGIN IF @S IS NULL RETURN(NULL)
DECLARE @NEW VARCHAR(50), @INDEX INT, @TEMP VARCHAR(50)
IF LEFT(@S, 1) <> @SPLIT SET @S = @SPLIT + @S IF RIGHT(@S, 1) <> @SPLIT SET @S = @S + @SPLIT
WHILE CHARINDEX(@SPLIT, @S) > 0 AND LEN(@S) <> 1 BEGIN SET @INDEX = CHARINDEX(@SPLIT, @S) SET @TEMP = LEFT(@S, CHARINDEX(@SPLIT, @S, @INDEX + LEN(@SPLIT)))
IF @NEW IS NULL SET @NEW = ISNULL(@NEW, '') + @TEMP ELSE SET @NEW = ISNULL(@NEW, '') + REPLACE(@TEMP, @SPLIT, '') + @SPLIT
WHILE CHARINDEX(@TEMP, @S) > 0 BEGIN SET @S = STUFF(@S, CHARINDEX(@TEMP, @S) + LEN(@SPLIT), CHARINDEX(@SPLIT, @S, CHARINDEX(@TEMP, @S) + LEN(@SPLIT)) - CHARINDEX(@TEMP, @S), '') END END
RETURN RIGHT(LEFT(@NEW, LEN(@NEW) - 1), LEN(LEFT(@NEW, LEN(@NEW) - 1)) - 1)ENDGO
测试示例
PRINT dbo.distinct_str('A,A,B,C,C,B,C,', ',')-- 结果:A,B,C
测试示例
PRINT dbo.distinct_str2('AABCCD')-- 结果:ABCD
实际应用场景
数据清洗:从脏数据中提取有效信息
地址解析:分离省市县等中文信息和门牌号等数字信息
用户输入处理:过滤特殊字符,只保留需要的字符类型
数据去重:处理标签、分类等重复项
性能优化建议
对于大数据量的处理,建议使用CLR函数替代标量函数
可以考虑将这些函数改写成内联表值函数
在调用时注意数据类型匹配,避免隐式转换
结语
这些自定义函数虽然简单,但在日常开发中却非常实用。您可以根据实际需求进行修改和扩展,比如添加对大小写英文的支持、提取特定范围内的数字等。
阅读原文:原文链接
该文章在 2026/4/15 18:02:47 编辑过