我有一个SQL字符串,结构如下:
@number <logical> @number <logical> ....
,
@SQL='((@1 or @2) and (@10 or @21))'
我想将字符串更新为:
@SQL='((con_1=1 or con_2=1) and (con_10=1 or con_21=1))'
意味着删除'@'并用'con_'代替它,保持数字(1位或更多)不变,并在数字后添加'=1'。
你知道怎么做吗?
请避免为其编写函数或过程。
您可以使用patindex
,stuff
或任何其他内置功能。
首先将字符串拆分为需要处理的值开头的'@'字符上的记录。
STUFF可用于在每条记录的值的最后一位数字后插入'=1'。我认为搜索最后一个数字比搜索第一个数字更难。反之则允许搜索第一个而不是最后一个。因为字符串是反向的,所以在反向数字的开头插入反向的'1='。如果没有数字,则原样返回所崇敬的值。
用'con_'而不是'@'串联起来。
declare @SQL varchar(200) = ' ((@1 or @2) and (@10 or @21)) @33 @55 ';
with split as (
select value, REVERSE(value) as [rev], PATINDEX('%[0-9]%', REVERSE(value)) as [pat]
FROM STRING_SPLIT(@SQL, '@')
), fixed as (
select value, rev, pat, CASE WHEN pat= 0 THEN REVERSE(rev) ELSE REVERSE(STUFF(rev, pat, 0, '1=')) END as [fix]
FROM split
) select STRING_AGG(fix, 'con_') from fixed
Result: ((con_1=1 or con_2=1) and (con_10=1 or con_21=1)) con_33=1 con_55=1
如果SQL server中包含正则表达式支持就好了。我认为这样做需要谨慎的实现,以避免使用所有的服务器资源。对数百万条记录或varchar(max)列进行正则表达式搜索....找到了使用SQL# (SQLsharp)的解决方案。
SQL#是一个。net/CLR库,驻留在SQL Server 2005(或更新版本)数据库中,并提供了一套用户定义函数、存储过程、用户定义聚合和用户定义类型。
我的解决方案:
declare @SQL varchar(200) = '@1 OR(@2 AND @3 AND (@4 or @5 or @6) AND (@7 or @8))'
SELECT SQL#.RegEx_Replace4k(@SQL, N'(@)+(d*)', N'CON_$2=1', -1, 1, N'')