如何在SQL Server中用新位置替换第二个位置字符串

时间:2018-08-24 09:04:50

标签: sql-server sql-server-2008 sql-server-2012

我有一个问题:在sql server中,如何将字符串happy的第二次出现替换为字符串new,否则保持原样(相同)。

表格:

CREATE TABLE [dbo].[stringrep](
    [name] [varchar](100) NULL,
    [id] [int] NULL
) 
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy happy year', 1)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'very happy new year', 2)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy new year hello', 3)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy  happy year', 4)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'heloo year happy', 5)
GO
INSERT [dbo].[stringrep] ([name], [id]) VALUES (N'happy happy happy year', 6)
GO

基于上述数据,我希望输出如下:

  id  |        Name 
  1   | happy new year
  2   | very happy new year
  3   | happy new year hello
  4   | happy  new year
  5   | heloo year happy
  6   |happy new happy year

我尝试了以下查询:

SELECT replace ( name  ,'happy happy year' ,'happy new year')afterreplacename,
replace (  name, substring ('happy happy year'  ,6,6) ,' new')anotherway
,name ,[id]
  FROM [test].[dbo].[stringrep]

上面的查询没有给出预期的结果。

请告诉我如何在sql server中完成此任务。

4 个答案:

答案 0 :(得分:2)

我设法提出以下查询。替换逻辑仅针对至少发生两次的happy数据。如果是这样,那么我们找到第二次出现的happy的索引,然后在STUFF中找到new作为替换。

SELECT
    data,
    CASE WHEN LEN(REPLACE(data, 'happy', '')) < LEN(data) - 6
         THEN STUFF(data,
                    CHARINDEX('happy', data, CHARINDEX('happy', data) + 1),
                     5,
                     'new')
         ELSE data END AS new_data
FROM yourTable;

enter image description here

Demo

请注意,此解决方案对于出现在字符串中任何位置的happy的两次(或更多次)事件是可靠的。有关这种极端情况,请参阅示例数据的最后一行。

我们想在这里使用正则表达式,也许您的问题可以单线回答。但是,SQL Server没有良好的本机正则表达式支持,因此我们不得不使用基本字符串函数。

答案 1 :(得分:0)

我发现第二次出现的happy,如果只有一次出现的happy返回了原始字符串,否则该字符串被分割了。我得到单词happy第二次出现之前的状态+ new +单词happy第二次出现之后的一切。

SELECT 
   CASE 
      WHEN CHARINDEX('happy', [name], (CHARINDEX('happy', [name])+1)) <> 0 THEN
            SUBSTRING([name],0,CHARINDEX('happy', [name], (CHARINDEX('happy', [name])+1))) 
            + 'new '
            + SUBSTRING([name],CHARINDEX('happy', [name], (CHARINDEX('happy', 
             [name])+1))+5,100)
      ELSE [name]  
   END 
FROM [dbo].[stringrep]

输出:

happy new  year
very happy new year
happy new year hello
happy  new  year
heloo year happy
happy new  happy year

答案 2 :(得分:0)

如果... SQL Server支持RegExes,那将是简单的RegEx。我建议使用其他工具替换值-具有数据库访问和RegEx支持的任何主要编程语言。如果这是经常操作,请使用CLR Functions。然后,请记住:

  

迭代是人的,递归神圣的

这就是为什么:

WITH Splitter AS
(
    SELECT id, 1 num, SUBSTRING(name, 1, charindex(' ',name)-1) Word, SUBSTRING(name, charindex(' ',name), LEN(name)) Rest FROM stringrep
    UNION ALL
    SELECT 
        id,
        num+1 num,
        CASE WHEN charindex(' ',Rest)=1 THEN ' '
             WHEN charindex(' ',Rest)=0 THEN Rest
             ELSE SUBSTRING(Rest, 1, charindex(' ',Rest)-1) END Word,
        CASE WHEN charindex(' ',Rest)=1 THEN SUBSTRING(Rest, 2, LEN(Rest))
             WHEN charindex(' ',Rest)=0 THEN ''
             ELSE SUBSTRING(Rest, charindex(' ',Rest), LEN(Rest)) END Rest
    FROM Splitter
    WHERE LEN(rest)>0
), Replacer AS
(
    SELECT S1.id, S1.num, CASE WHEN LastNotSpace='happy' AND Word='happy' AND (LastLastNotSpace IS NULL OR LastLastNotSpace!='happy') THEN 'new' ELSE Word END NewWord
    FROM Splitter S1
    LEFT JOIN (SELECT id,num,LAG(Word) OVER (PARTITION BY id ORDER BY num) LastNotSpace, LAG(Word,2) OVER (PARTITION BY id ORDER BY num) LastLastNotSpace FROM Splitter WHERE Word!=' ') T ON S1.id=T.id AND S1.num=T.num
), Joiner AS
(
    SELECT id, num, CAST(NewWord AS nvarchar(MAX)) Joined FROM Replacer WHERE num=1
    UNION ALL
    SELECT S.id, S.num, J.Joined+S.NewWord Joined FROM Joiner J
    JOIN Replacer S ON J.id=S.id AND J.num+1=S.num
), Filter AS
(
    SELECT id, Joined FROM (
        SELECT id, num, Joined, ROW_NUMBER() OVER (PARTITION BY id ORDER BY num DESC) Lev FROM Joiner
    ) T WHERE Lev=1
)
SELECT * FROM Filter

答案 3 :(得分:0)

尝试一下:

select [name], id, 
       case when secondIndex > 0 then stuff([name], secondIndex, 5, 'new') else [name] end newName
from (
    select [name], id, charindex('happy', [name], charindex('happy', [name]) + 1) secondIndex
    from #stringrep
) a