Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 使用正则表达式(或类似表达式)更新字段_Sql Server_Regex_Database_Sql Server 2008_Tsql - Fatal编程技术网

Sql server 使用正则表达式(或类似表达式)更新字段

Sql server 使用正则表达式(或类似表达式)更新字段,sql-server,regex,database,sql-server-2008,tsql,Sql Server,Regex,Database,Sql Server 2008,Tsql,在我的表中有一个名为Url的字段,如下所示: /MyServer/MyPage?Param=XXX 我需要运行一个脚本,以便将该字段从XXX更新为YYY。我确实有规则说明YYY与XXX对应的是什么,问题是我不知道如何只更新参数为exacltyparam的字段,而不知道如何更新其他字段 因此,这些将是更新: /MyServer/MyPage?Param=XXX ==> /MyServer/MyPage?Param=XXX /MyServer/MyOtherPage?Par

在我的表中有一个名为Url的字段,如下所示:
/MyServer/MyPage?Param=XXX

我需要运行一个脚本,以便将该字段从
XXX
更新为
YYY
。我确实有规则说明YYY与XXX对应的是什么,问题是我不知道如何只更新参数为exaclty
param
的字段,而不知道如何更新其他字段

因此,这些将是更新:

/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)
我说清楚了吗

编辑:我有一个辅助表,对应于
XXX
YYY
。请记住,
XXX
只是一个例子。实际上,参数是一个整数,因此参数值的长度是可变的

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
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

这解决了Mikael的顾虑,即
AAA
XXX
等可能出现在URL中。它还处理参数不是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
/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
添加后续问题的文档链接。是的,
STUFF
是一个函数


这里有一个
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;
结果:

Col
--------------------------------------------------
/MyServer/MyPage?Param=XXX
/MyServer/MyOtherPage?Param=BBB
/MyServer/MyOtherPage?Param2=JJJ
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

只是为了好玩,因为最初的问题确实提到了正则表达式,我想我会给出一个使用正则表达式的例子。是的,这确实需要SQLCLR,不是每个人都可以或将使用它,但这是一个选项

本例确实使用了一个现有的SQLCLR库,我是该库的作者,但是正则表达式函数(只有3个例外)是免费的

该示例使用Aaron Bertrand答案中的示例URL和规则表变量,但将“source”字符串更改为数字(因为这是原始请求,正则表达式在这方面是特定的),并且我添加了一个测试用例以显示字符串“222”与“2222”的任何部分都不匹配


公平地说,严格的T-SQL解决方案并没有测试性能,而是测试功能性和灵活性。哪种解决方案性能更好,必须在您的服务器上进行测试。

第一行是否表示在“after”值的末尾有YYY?另外,您使用的是什么版本的SQL Server?我使用的是SQL Server 2008,是的,要替换的字符串总是在+1奇怪的时间末尾。我使用了
STUFF
,因为我认为如果参数实际上不在字符串的末尾,则更容易调整。@AaronBertrand-是的,STUFF很好。我认为您应该在回答中使用REVERSE进行一些计算,以找到字符串的最后一个匹配项。我使用了一个稍微不同的路径,最终结果相同。如果Param2=AAA,这将错误地将其更改为Param2=BBB。另外,Param=AAAA变成Param=ABBB。@JohnDewey谢谢,我想已经修复了。如果参数也是URL的一部分,这可能会给您带来麻烦
/MyAAAServer/MyOtherPage?Param=AAA
变成
/MyBBBServer/MyOtherPage?Param=AAA
。谢谢@Mikael,我想我已经解决了。嗯,是的,再次感谢。很明显,我在个人和联合之间进行了交换。@AaronBertrand-我认为如果您将硬编码的
参数=
移动到
@rules
,并将
I+7
替换为
I+1
,您将获得更大的灵活性。通过这种方式,
@rules
可以混合其他参数,例如
param2=CCCC
=>
param2=MM
等。为什么要在1=1时加入,然后在where子句中添加加入加入条件?我知道这是合法的,有效的,但这是一个没有明显目的的附加条款。我想问一下replacements表中identity列的用途,但我对join更感兴趣。为什么会出现while循环?你的更新不应该一下子影响整个场景吗?@AaronBertrand-谢谢你指出这些。
WHILE
id
是上一次迭代遗留下来的行李,现在已经过时了。更简单的查询被更新了。哦,太恐怖了!非ANSI连接?老实说,我更喜欢1=1的答案-/@AaronBertrand——逻辑上它相当于1=1,但我认为是旧的ANSI-86标准。但是为什么不在pat索引上进行内部连接呢?IMHO,旧的样式并不是永久化和鼓励的好做法,因为它太容易意外地进入笛卡尔坐标系,而且更改为外部联接也会带来痛苦(因为*=/=*已被弃用)。