所以我的表中有一个名为Url的字段,如下所示:
/MyServer/MyPage?Param=XXX
。
我需要运行一个脚本才能将该字段从XXX
更新为YYY
。我确实有关YYY
对应XXX
的内容的规则,我不知道如何只更新其param为exaclty Param
而不是其他的字段。< / p>
所以这些将是更新:
/MyServer/MyPage?Param=XXX ==> /MyServer/MyPage?Param=XXX
/MyServer/MyOtherPage?Param=AAA ==> /MyServer/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ ==> /MyServer/MyOtherPage?Param2=JJJ
(last row no changes since it is not param)
我清楚了吗?
修改:我有一个带有correpsondation XXX
YYY
的辅助表。请记住XXX
只是一个例子。实际上参数是一个整数,因此参数值的长度是可变的
答案 0 :(得分:2)
这解决了Mikael的担忧,AAA
,XXX
等可能会出现在网址中。它还处理参数不是URL中最后一个参数的情况。
DECLARE @URLs TABLE (URL VARCHAR(2000));
INSERT @URLs SELECT '/MyServer/MyPage?Param=XXX'
UNION ALL SELECT '/MyServer/MyOtherPage?Param=AAA'
UNION ALL SELECT '/MyServerAAA/MyOtherPage?Param=AAA'
UNION ALL SELECT '/MyServer/MyOtherPage?Param2=JJJ'
UNION ALL SELECT '/MyServer/MyOtherPage?Param=AAA&Param2=JJJ'
UNION ALL SELECT '/MyServer/MyOtherPage?Param2=AAA&Param=AAA';
DECLARE @rules TABLE(pSrc VARCHAR(32), pDest VARCHAR(32));
INSERT @rules SELECT 'XXX', 'YYY'
UNION ALL SELECT 'AAA', 'BBB'
UNION ALL SELECT 'JJJ', 'KKK';
;WITH src AS
(
SELECT URL,
pre = LEFT(URL, CHARINDEX('?', URL)-1),
post = SUBSTRING(URL, CHARINDEX('?', URL), 2000)
FROM @URLs
), sub AS
(
SELECT src.URL, src.pre, src.post, r.pSrc, r.pDest,
i = PATINDEX('%[?&]Param=' + r.pSrc + '&%', post + '&')
FROM src INNER JOIN @Rules AS r
ON src.post + '&' LIKE '%[?&]Param=' + r.pSrc + '&%'
)
UPDATE u SET URL = pre + STUFF(post, i+7, LEN(pSrc), pDest)
FROM @URLs AS u INNER JOIN sub ON u.URL = sub.URL;
SELECT * FROM @URLs;
结果:
URL
--------------------------------
/MyServer/MyPage?Param=YYY
/MyServer/MyOtherPage?Param=BBB
/MyServerAAA/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ
/MyServer/MyOtherPage?Param=BBB&Param2=JJJ
/MyServer/MyOtherPage?Param2=AAA&Param=BBB
为后续问题添加文档链接。是的,STUFF
是一个功能。
答案 1 :(得分:1)
declare @T table
(
Col varchar(50)
)
insert into @T values
('/MyServer/MyPage?Param=XXX'),
('/MyServer/MyOtherPage?Param=AAA'),
('/MyServer/MyOtherPage?Param2=JJJ')
declare @P table
(
ID int,
P1 varchar(50),
P2 varchar(50)
)
insert into @P values
(1, 'AAA', 'BBB'),
(2, 'XXX', 'YYY')
update T
set Col = left(T.Col, len(T.Col)-len(P.P1))+P.P2
from @T as T
inner join @P as P
on right(T.Col, len(P.P1)+6) = 'Param='+P.P1
where P.ID = 1
select *
from @T
结果:
Col
--------------------------------------------------
/MyServer/MyPage?Param=XXX
/MyServer/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ
答案 2 :(得分:0)
这是replace()
方法。
编辑:增加了灵活性。
declare @myURLs table(url varchar(1000))
insert into @myURLs values ('/MyServer/MyPage?Param=XXX&Param2=JJJ'); --should update
insert into @myURLs values ('/MyServer/MyPage?Param2=XXX'); --should not update
insert into @myURLs values ('/MyServer/MyOtherPage?Param2=JJJ&Param=AAA'); --should update
insert into @myURLs values ('/MyServer/MyOtherPage?Param=AAAA'); --should not update
insert into @myURLs values ('/MyServer/MyOtherPage?Param=AAAA&Param2=JJJ'); --should not update
declare @replacements table(targetStr varchar(80), replStr varchar(80));
insert into @replacements values ('Param=AAA','Param=BBB');
insert into @replacements values ('Param=XXX','Param=YYY');
-- ANSI-92 syntax
update u
set url=REPLACE(url,r.targetStr,r.replStr)
from @myURLs u
inner join @replacements r on
(PATINDEX('%[?&]'+r.targetStr,url)>0
or PATINDEX('%[?&]'+r.targetStr+'[?&]%',url) > 0);
SELECT *
FROM @myURLs;
结果:
url
------------------------------------------------
/MyServer/MyPage?Param=YYY&Param2=JJJ
/MyServer/MyPage?Param2=XXX
/MyServer/MyOtherPage?Param2=JJJ&Param=BBB
/MyServer/MyOtherPage?Param=AAAA
/MyServer/MyOtherPage?Param=AAAA&Param2=JJJ
答案 3 :(得分:0)
只是为了它的乐趣,并且因为原始问题确实提到了RegEx,我想我会给出一个使用正则表达式的例子。是的,这确实需要SQLCLR并不是每个人都可以或将使用它,但它是一个选项。
此示例使用名为SQL# (SQLsharp)的现有SQLCLR库,我是作者,但正则表达式函数(仅有3个例外)是免费的。
该示例使用Aaron Bertrand的答案中的示例URL和规则表变量,但将“源”字符串更改为数字(因为这是原始请求,而正则表达式在这方面是特定的)并且我添加了一个测试-case表示字符串“222”与“2222”的任何部分都不匹配。
DECLARE @URLs TABLE (URL VARCHAR(2000));
INSERT @URLs SELECT '/MyServer/MyPage?Param=111'
UNION ALL SELECT '/MyServer/MyOtherPage?Param=222'
UNION ALL SELECT '/MyServer222/MyOtherPage?Param=222'
UNION ALL SELECT '/MyServer222/MyOtherPage?Param=2222'
UNION ALL SELECT '/MyServer/MyOtherPage?Param2=333'
UNION ALL SELECT '/MyServer/MyOtherPage?Param=222&Param2=333'
UNION ALL SELECT '/MyServer/MyOtherPage?Param=2222&Param2=333'
UNION ALL SELECT '/MyServer/MyOtherPage?Param2=222&Param=222';
DECLARE @Rules TABLE(pSrc VARCHAR(32), pDest VARCHAR(32));
INSERT @Rules SELECT '111', 'YYY'
UNION ALL SELECT '222', 'BBB'
UNION ALL SELECT '2222', 'bbb'
UNION ALL SELECT '333', 'KKK';
SELECT SQL#.RegEx_Replace(u.url,
'(.*Param=)' + r.pSrc + '([^0-9]+|$)',
'$1' + r.pDest + '$2',
-1, 1, '')
FROM @URLs u
CROSS JOIN @Rules r
WHERE SQL#.RegEx_IsMatch(u.url,
'(.*Param=)' + r.pSrc + '([^0-9]+|$)',
1, '') = 1
-- OR, using RegEx look-behind and look-ahead
SELECT SQL#.RegEx_Replace(u.url,
'(?<=Param=)' + r.pSrc + '(?=[^0-9]+|$)',
r.pDest,
-1, 1, '')
FROM @URLs u
CROSS JOIN @Rules r
WHERE SQL#.RegEx_IsMatch(u.url,
'(?<=Param=)' + r.pSrc + '(?=[^0-9]+|$)',
1, '') = 1
结果:
/MyServer/MyPage?Param=YYY
/MyServer/MyOtherPage?Param=BBB
/MyServer222/MyOtherPage?Param=BBB
/MyServer222/MyOtherPage?Param=bbb
/MyServer/MyOtherPage?Param=BBB&Param2=333
/MyServer/MyOtherPage?Param=bbb&Param2=333
/MyServer/MyOtherPage?Param2=222&Param=BBB
为了公平对待严格的T-SQL解决方案,这不是针对性能而是针对功能性和灵活性进行测试的。哪个解决方案性能更好,必须在您的服务器上进行测试。