2017-02-09 3 views
1

문자열 형식의 'F250N'열에서 알려진 char ']'과 '[G56]'사이의 모든 값을 삭제하고 싶습니다. 표 'T250'char와 expression 사이의 문자열 값을 삭제하는 방법 -

이것은 앞 글자가 발견되지 않는 경우도 포함해야합니다. 문자열의 시작 부분에.

예 :

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] 앞의 문자열의 부분을 고려하지 않습니다 마지막 ]

+1

는 상태, 무엇 [G56] 종료 토큰이 첫 번째가 될 것입니다 경계 사건에 대해 " ']'알려진 문자"? – dlatikay

+0

원하는 출력물이 사용자의 질문보다 훨씬 복잡합니다. 두 번째 예제는']'문자 다음에 문자를 제거하는 것이 아니라'[G62] LVN-'부분 전체를 제거하는 것입니다. 여기 규칙에 좀 더 구체적으로 설명하십시오. – iamdave

+1

더 긴 예에서, 나머지 모든 "토큰"은 [G56]으로 끝납니다. 그래서 첫 번째뿐만 아니라 모든 발생을 제거해야합니다. – dlatikay

답변

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 @[email protected][email protected] 
     end else begin 
     set @[email protected] 
     end 
    end else begin 
     break 
    end 
    --fuse 
    if len(@s)[email protected] break 
    end 
    --persist 
    update t set [email protected] from @T250 t where [email protected] 
    --advance 
    fetch next from c into @pk, @s 
end 
close c 
deallocate c 

--after 
select F250N from @T250 

나는 경계 사례를 테스트하지 않았지만, 적어도 끝없는 반복을 가지지 않을 것입니다.

0

내가 사랑하는 또는 Oracle이하는 같은 모든 tom-foolery없이 regex를 지원하지 않는 T-SQL을 싫어하면 난 아직도 결정할 수 없습니다 ...

어떤 사람들은, 문제에 직면했을 때, 나는 "생각 나는 정규 표현식을 사용할 것이다. " 이제 그들은 두 가지 문제가 있습니다. - Programming Aphorism

솔직히 그래, 정규 표현식 문제 (데이터베이스 설계 문제는 제외)처럼 보입니다. T-SQL은 정규식을 회피하지만 CLR을 통해 지원 될 수 있습니다.

자세히 알아보기 here. Godspeed!

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

> 1 분기로 작은 편집 – dfundako