如何删除char和表达式之间的字符串值 - SQL Server

时间:2017-02-09 17:13:47

标签: sql sql-server string replace sql-server-2014

我想删除表'T250'中已知字符'''和表达式'[G56]'之间的字符串'F250N'中的所有值

这还需要涵盖无法找到前面的char的情况,例如。在字符串的开头。

例如:

 SYSADMIN[G63]Z-GHQ[G62]Z-WE[G56]Z-MEX[G56]Z-NAZ[G56]Z-LAS[G56]Z-LAN[G56]Z-CEE[G56]Z-APAC[G56]Z-CAD[G56]

会变成:

 SYSADMIN[G63]Z-GHQ[G62]

LVN-CHNG[G62]LVN-READ[G56]LVN-FULL[G63]

会变成:

LVN-CHNG[G62]LVN-FULL[G63]

到目前为止,我尝试过类似的事情:

update T250 
set F250N = replace(F250N, '[G56]', '') 
from T250

然而,这并没有考虑到[G56]之前的字符串部分到最后]

3 个答案:

答案 0 :(得分:1)

无法想出在UPDATE子句中解决此内联的方法。所以会有这种程序方法:

set nocount on

declare
  @T250 table(pk int primary key, F250N nvarchar(max))
declare
  @s nvarchar(max),
  @pk int,
  @i int,
  @left nvarchar(max),
  @right nvarchar(max),
  @lenbefore int

insert @T250 values
  (1, N'SYSADMIN[G63]Z-GHQ[G62]Z-WE[G56]Z-MEX[G56]Z-NAZ[G56]Z-LAS[G56]Z-LAN[G56]Z-CEE[G56]Z-APAC[G56]Z-CAD[G56]'),
  (2,N'LVN-CHNG[G62]LVN-READ[G56]LVN-FULL[G63]')

--before
select F250N from @T250

declare c cursor for select pk, F250N from @T250
where F250N like N'%[[]G56]%' --skip rows that do not even contain the marker
open c
fetch next from c into @pk,@s
while @@FETCH_STATUS=0 begin
  --handle single value
  set @lenbefore=len(@s)
  while @s like N'%[[]G56]%' begin
    set @i=CHARINDEX(N'[G56]', @s)
    if @i>0 begin
      set @right=SUBSTRING(@s, @i+len(N'[G56]'),len(@s))
      set @left = REVERSE(substring(@s, 1, @i - 1))
      if @i>0 begin
        set @left=reverse(SUBSTRING(@left,@i,len(@left)))
        set @s=@left+@right
      end else begin
        set @s=@right
      end
    end else begin
      break
    end
    --fuse
    if len(@s)=@lenbefore break
  end
  --persist
  update t set t.F250N=@s from @T250 t where t.pk=@pk
  --advance
  fetch next from c into @pk, @s
end
close c
deallocate c

--after
select F250N from @T250

我没有测试边框情况,但至少它不会进入无限循环。

答案 1 :(得分:0)

如果没有像Oracle一样的所有tom-foolery,我仍然无法决定是否喜欢T-SQL而不支持regex ...

  

有些人在面对问题时会想到,我知道,我会使用正则表达式。"现在他们有两个问题。 - Programming Aphorism

老实说,这看起来像是一个正则表达式问题(除了数据库设计问题)。虽然T-SQL是正则表达式,但它可以通过CLR支持。

了解更多here。一帆风顺!

答案 2 :(得分:0)

这是我对它的抨击。首先,找一个拆分功能。这是我使用的那个: http://www.sqlservercentral.com/blogs/querying-microsoft-sql-server/2013/09/19/how-to-split-a-string-by-delimited-char-in-sql-server/

这适用于您的两个样本。提供更多,我们会看到。

IF OBJECT_ID('tempdb..#holdingtable') IS NOT NULL
    DROP TABLE #holdingtable

--DECLARE @ VARCHAR(1000) = REPLACE('SYSADMIN[G63]Z-GHQ[G62]Z-WE[G56]Z-MEX[G56]Z-NAZ[G56]Z-LAS[G56]Z-LAN[G56]Z-CEE[G56]Z-APAC[G56]Z-CAD[G56]', '[G56]', ',')

declare @ varchar(1000) = REPLACE('LVN-READ[G56]LVN-CHNG[G62]LVN-READ[G56]LVN-FULL[G63]LVN-READ[G56]', '[G56]', ',')
SELECT *
INTO #holdingtable
FROM [fnSplitString](@, ',')

IF (
        SELECT COUNT(*)
        FROM #holdingtable
        WHERE splitdata LIKE '%[[]%'
        ) > 1
BEGIN
        ;

    WITH cte
    AS (
        SELECT LEFT(splitdata, LEN(splitdata) - CHARINDEX(']', REVERSE(splitdata)) + 1)  AS col_
        FROM #holdingtable
        WHERE LEFT(splitdata, LEN(splitdata) - CHARINDEX(']', REVERSE(splitdata)) + 1) LIKE '%[[]%'
        )
    SELECT col_ AS [text()]
    FROM cte
    ORDER BY col_
    FOR XML PATH('')
END
ELSE IF (
        SELECT COUNT(*)
        FROM #holdingtable
        WHERE splitdata LIKE '%[[]%'
        ) = 1
BEGIN
    SELECT LEFT(splitdata, LEN(splitdata) - CHARINDEX(']', REVERSE(splitdata)) + 1)
    FROM #holdingtable
    WHERE LEFT(splitdata, LEN(splitdata) - CHARINDEX(']', REVERSE(splitdata)) + 1) LIKE '%[[]%'
END