如何在SQL中替换字符?

时间:2018-09-21 10:58:54

标签: sql sql-server

给出: xml字符串包含如下子字符串:

N'<node action="i" s=""petya""></node>'

如果字符串包含双“”,我该怎么做:

  1. 用action =“ u”替换action =任何字符。
  2. 将“”替换为“。

例如,结果:

N'<node action="u" s="petya"></node>'

2 个答案:

答案 0 :(得分:2)

用您的列名替换@String:

DECLARE @string NVARCHAR(100)=N'<node action="i" s=""petya""></node>'

SELECT CASE WHEN @string LIKE '%""%' THEN 
REPLACE(SUBSTRING(@STRING,1,CHARINDEX('action="',@string,1)-1)+'action="u"'
        +SUBSTRING(@STRING,CHARINDEX('action="',@string,1)+10,LEN(@STRING)),'""','"') 
        ELSE @STRING END

答案 1 :(得分:2)

晚期答案-只是提出一种替代方法(已经+1 Luv)

示例

Declare @S nvarchar(max) = N'<node action="i" s=""petya""></node>'

Select @S = replace(@S,sFrom,sTo)
 From ( values ( 'action="i"','action="u"')
              ,( 'action="a"','action="u"')
              ,( 'action="d"','action="u"')   -- Assuming a limited number of actions
              ,( '=""','="')                  -- Leading ""
              ,( '"">','">')                  -- Trailing ""
              ,( '"" ','" ')                  -- Trailing ""
      ) A(sFrom,sTo)


Select @S

返回

<node action="u" s="petya"></node>
  

编辑-用于多个/条件节点

Declare @S nvarchar(max) = N'<node action="i" n="0" s=""petya""></node> <node action="i" n="2" s="vasya"></node>' 

;with cte as (
Select A.RetSeq
      ,A.RetVal
      ,NewVal = case when patindex('%""[a-z,0-1]%""%',A.RetVal)=0 
                     then A.RetVal
                     else replace(stuff(A.RetVal,B.RetPos,len(B.RetVal),'u'),'""','"')
                     end
 From  [dbo].[tvf-Str-Extract](@S,'<','>') A
 Outer Apply [dbo].[tvf-Str-Extract](A.RetVal,'action="','" ') B
)
Select @S = Stuff((Select '<' +NewVal+'>' From cte Order By RetSeq For XML Path(''),TYPE).value('(./text())[1]','varchar(max)'),1,0,'')

Select convert(xml,@S)

返回有效的XML

<node action="u" n="0" s="petya" />
<node action="i" n="2" s="vasya" />

表值函数

厌倦了提取字符串(左,右,charindex,patindex等),我修改了一个parse / split函数以接受两个非相似的定界符。

CREATE FUNCTION [dbo].[tvf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100))
Returns Table 
As
Return (  

with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
       cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A ),
       cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
       cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S)

Select RetSeq = Row_Number() over (Order By N)
      ,RetPos = N
      ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 
 From  (
        Select *,RetVal = Substring(@String, N, L) 
         From  cte4
       ) A
 Where charindex(@Delimiter2,RetVal)>1

)
/*
Max Length of String 1MM characters

Declare @String varchar(max) = 'Dear [[FirstName]] [[LastName]], ...'
Select * From [dbo].[tvf-Str-Extract] (@String,'[[',']]')
*/