영문자 이외의 문자를 SQL Server의 문자열에서 제거하는 방법은 무엇입니까?


172

문자열에서 알파벳이 아닌 모든 문자를 어떻게 제거 할 수 있습니까?

영숫자가 아닌 것은 어떻습니까?

이것이 사용자 정의 기능이어야합니까, 아니면 더 일반화 가능한 솔루션이 있습니까?

답변:


362

이 기능을 사용해보십시오 :

Create Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin

    Declare @KeepValues as varchar(50)
    Set @KeepValues = '%[^a-z]%'
    While PatIndex(@KeepValues, @Temp) > 0
        Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')

    Return @Temp
End

다음과 같이 호출하십시오.

Select dbo.RemoveNonAlphaCharacters('abc1234def5678ghi90jkl')

코드를 이해하면 다른 문자도 제거하기 위해 코드를 변경하는 것이 비교적 간단하다는 것을 알 수 있습니다. 검색 패턴을 전달할 수있을 정도로 동적으로 만들 수도 있습니다.

도움이 되길 바랍니다.


9
이 코드는 비 알파 문자를 제거합니다 (따라서 숫자도 제거됨). 숫자를 남기지 않으려면 (알파 숫자가 아닌 문자 제거) ^ az를 ^ az ^ 0-9로 바꾸십시오. 해당 검색 문자열은 코드에서 두 가지 다른 위치에 나타납니다. 두 가지를 모두 교체하십시오.
George Mastros

26
Jeff의 의견 : 나는 문자가 아닌 숫자와 숫자가 아닌 것을 모두 제거하려면 '^ a-z0-9'( '^ az ^ 0-9'와 반대로 ^를 문자열에 남겨 두십시오)를 원한다고 생각합니다. .
심지어 Mien

1
조지 +1 "Set-Based"코드와 Inline Scalar Functions를 사용하여 Row-By-Row를 치는 데 큰 어려움이있는 곳 중 하나입니다. 잘 했어요 나는 또한 몇 년 동안 동일한 기본 형식을 가진 "초기 모자"기능을 사용해 왔습니다.
Jeff Moden

6
@Lynchie Change '% [^ az] %'To '% [^ az] %'기본적으로 z 뒤에 공백 문자를 넣으십시오.
George Mastros

8
변수 이름 KeepValues는 실제로 의도 한 것과 반대입니다. KeepValues에는 제외해야 할 문자가 나열되어 있습니다.
nee21

167

G Mastros멋진 답변 의 매개 변수화 된 버전 :

CREATE FUNCTION [dbo].[fn_StripCharacters]
(
    @String NVARCHAR(MAX), 
    @MatchExpression VARCHAR(255)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    SET @MatchExpression =  '%['+@MatchExpression+']%'

    WHILE PatIndex(@MatchExpression, @String) > 0
        SET @String = Stuff(@String, PatIndex(@MatchExpression, @String), 1, '')

    RETURN @String

END

알파벳 만 :

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z')

숫자 만 :

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^0-9')

영숫자 만 :

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z0-9')

영숫자가 아닌 :

SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', 'a-z0-9')

3
이 버전을 선호하고 아래로 스크롤하기 전에 G Mastros의 답변에 대한 내 적응을 만들었습니다.
earnshavian

정규식 패턴이 모든 공백에서 작동하지 않는 것 같습니다. 영숫자와 공백을 제외한 모든 특수 문자를 제거하려면 SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9\s')여전히 공백을 제거하는 것이 필요합니다. 또한 사용하려고했지만 [[:blank:]]함수가 중단되고 문자열에서 아무것도 제거되지 않습니다. 내가 얻은 가장 가까운 것은 다음을 사용하는 것입니다 SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9 ')(정규 패턴의 공백을 하드 코딩). 그러나 줄 바꿈을 제거하지는 않습니다.
Billy McKee

2
@BillyMcKee 정규 표현식 끝에 공백을 추가하는 대신 처음에 공백을 추가하십시오. SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^ a-z0-9')
Mike

8

내 시스템 에서이 추악한 기능은 G Mastros 우아한 기능보다 성능이 뛰어납니다.

CREATE FUNCTION dbo.RemoveSpecialChar (@s VARCHAR(256)) 
RETURNS VARCHAR(256) 
WITH SCHEMABINDING
    BEGIN
        IF @s IS NULL
            RETURN NULL
        DECLARE @s2 VARCHAR(256) = '',
                @l INT = LEN(@s),
                @p INT = 1

        WHILE @p <= @l
            BEGIN
                DECLARE @c INT
                SET @c = ASCII(SUBSTRING(@s, @p, 1))
                IF @c BETWEEN 48 AND 57
                   OR  @c BETWEEN 65 AND 90
                   OR  @c BETWEEN 97 AND 122
                    SET @s2 = @s2 + CHAR(@c)
                SET @p = @p + 1
            END

        IF LEN(@s2) = 0
            RETURN NULL

        RETURN @s2

일반적인 쉼표, 마침표, 공백 등은 어떻습니까?
sojim

사용하지 않는 경우 얼마나 다를 ASCII여기에 정수 직접 출력 비교 SUBSTRING: 일부 문자, 예를 들면와를 SET @ch=SUBSTRING(@s, @p, 1)하고IF @ch BETWEEN '0' AND '9' OR @ch BETWEEN 'a' AND 'z' OR @ch BETWEEN 'A' AND 'Z' ...
S.Serpooshan

함수와 마찬가지로 WITH SCHEMABINDING을 그의 함수에 추가하십시오. VARCHAR을 사용하고 있으며 그의 기능은 NVARCHAR을 사용하고 있습니다. 그의 함수에 전달하는 매개 변수가 VARCHAR 인 경우 그의 함수 내에서 NVARCHAR 대신 VARCHAR을 사용해야합니다. 그렇지 않으면 시스템은 문자열 값을 VARCHAR에서 NVARCHAR로 캐스트해야 더 비싼 기능을 수행 할 수 있습니다. 이러한 변경에도 불구하고 귀하의 기능은 여전히 ​​빠를 수 있지만, 몇 가지 예입니다. 귀하의 상황에서 귀하의 기능이 더 느리게 수행되는 위치를 볼 수 있습니다.
EricI

1
그의 함수는 NVARCHAR (MAX)를 사용하고 있으며 함수는 VARCHAR (256)을 사용하고 있습니다. 256이 필요한 모든 경우 VARCHAR (256)도 사용하도록 그의 기능을 변경하면 그의 기능이 더 빨리 작동합니다.
EricI

5

SQL이 문자열 조작에 좋지 않다는 것을 알았지 만 이것이 어렵다고 생각하지 않았습니다. 다음은 문자열에서 모든 숫자를 제거하는 간단한 함수입니다. 이를 수행하는 더 좋은 방법이 있지만 이것은 시작입니다.

CREATE FUNCTION dbo.AlphaOnly (
    @String varchar(100)
)
RETURNS varchar(100)
AS BEGIN
  RETURN (
    REPLACE(
      REPLACE(
        REPLACE(
          REPLACE(
            REPLACE(
              REPLACE(
                REPLACE(
                  REPLACE(
                    REPLACE(
                      REPLACE(
                        @String,
                      '9', ''),
                    '8', ''),
                  '7', ''),
                '6', ''),
              '5', ''),
            '4', ''),
          '3', ''),
        '2', ''),
      '1', ''),
    '0', '')
  )
END
GO

-- ==================
DECLARE @t TABLE (
    ColID       int,
    ColString   varchar(50)
)

INSERT INTO @t VALUES (1, 'abc1234567890')

SELECT ColID, ColString, dbo.AlphaOnly(ColString)
FROM @t

산출

ColID ColString
----- ------------- ---
    1 abc1234567890 abc

라운드 2-데이터 중심 블랙리스트

-- ============================================
-- Create a table of blacklist characters
-- ============================================
IF EXISTS (SELECT * FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.CharacterBlacklist'))
  DROP TABLE dbo.CharacterBlacklist
GO
CREATE TABLE dbo.CharacterBlacklist (
    CharID              int         IDENTITY,
    DisallowedCharacter nchar(1)    NOT NULL
)
GO
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'0')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'1')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'2')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'3')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'4')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'5')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'6')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'7')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'8')
INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'9')
GO

-- ====================================
IF EXISTS (SELECT * FROM sys.objects WHERE [object_id] = OBJECT_ID('dbo.StripBlacklistCharacters'))
  DROP FUNCTION dbo.StripBlacklistCharacters
GO
CREATE FUNCTION dbo.StripBlacklistCharacters (
    @String nvarchar(100)
)
RETURNS varchar(100)
AS BEGIN
  DECLARE @blacklistCt  int
  DECLARE @ct           int
  DECLARE @c            nchar(1)

  SELECT @blacklistCt = COUNT(*) FROM dbo.CharacterBlacklist

  SET @ct = 0
  WHILE @ct < @blacklistCt BEGIN
    SET @ct = @ct + 1

    SELECT @String = REPLACE(@String, DisallowedCharacter, N'')
    FROM dbo.CharacterBlacklist
    WHERE CharID = @ct
  END

  RETURN (@String)
END
GO

-- ====================================
DECLARE @s  nvarchar(24)
SET @s = N'abc1234def5678ghi90jkl'

SELECT
    @s                  AS OriginalString,
    dbo.StripBlacklistCharacters(@s)   AS ResultString

산출

OriginalString           ResultString
------------------------ ------------
abc1234def5678ghi90jkl   abcdefghijkl

독자에 대한 나의 도전 : 이것을보다 효율적으로 만들 수 있습니까? 재귀를 사용하는 것은 어떻습니까?


sommarskog.se/arrays-in-sql-2005.html#tblnum 블랙리스트 테이블에 결합 된 숫자 테이블을 사용하여 루프없이 더 나은 dbo.StripBlacklistCharacters ()를 작성할 수는 있지만 오늘 시도하기에는 너무 게으르다. 나 자신 ..
KM.

4

나와 같은데 프로덕션 데이터에 함수를 추가 할 수는 없지만 여전히 이런 종류의 필터링을 수행하려는 경우 PIVOT 테이블을 사용하여 필터링 된 조각을 다시 모으는 순수한 SQL 솔루션이 있습니다.

NB 표를 최대 40 자로 하드 코딩했습니다. 필터링 할 문자열이 더 길면 더 추가해야합니다.

SET CONCAT_NULL_YIELDS_NULL OFF;

with 
    ToBeScrubbed
as (
    select 1 as id, '*SOME 222@ !@* #* BOGUS !@*&! DATA' as ColumnToScrub
),

Scrubbed as (
    select 
        P.Number as ValueOrder,
        isnull ( substring ( t.ColumnToScrub , number , 1 ) , '' ) as ScrubbedValue,
        t.id
    from
        ToBeScrubbed t
        left join master..spt_values P
            on P.number between 1 and len(t.ColumnToScrub)
            and type ='P'
    where
        PatIndex('%[^a-z]%', substring(t.ColumnToScrub,P.number,1) ) = 0
)

SELECT
    id, 
    [1]+ [2]+ [3]+ [4]+ [5]+ [6]+ [7]+ [8] +[9] +[10]
    +  [11]+ [12]+ [13]+ [14]+ [15]+ [16]+ [17]+ [18] +[19] +[20]
    +  [21]+ [22]+ [23]+ [24]+ [25]+ [26]+ [27]+ [28] +[29] +[30]
    +  [31]+ [32]+ [33]+ [34]+ [35]+ [36]+ [37]+ [38] +[39] +[40] as ScrubbedData
FROM (
    select 
        *
    from 
        Scrubbed
    ) 
    src
    PIVOT (
        MAX(ScrubbedValue) FOR ValueOrder IN (
        [1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
        [11], [12], [13], [14], [15], [16], [17], [18], [19], [20],
        [21], [22], [23], [24], [25], [26], [27], [28], [29], [30],
        [31], [32], [33], [34], [35], [36], [37], [38], [39], [40]
        )
    ) pvt

이 솔루션은 235K 행 집합에서 함수를 사용하는 것보다 2.3 배 빠릅니다. 또한 2 배의 교체 작업을 수행해야했으며 총 4 개의 CTE를 사용했습니다. 챔피언처럼 일했습니다.
JJS

4

주어진 모든 솔루션을 살펴본 결과 함수 또는 CTE / XML 쿼리가 필요하지 않고 중첩 된 REPLACE 문을 유지 관리하는 데 어려움이없는 순수한 SQL 메서드가 있어야한다고 생각했습니다. 내 해결책은 다음과 같습니다.

SELECT 
  x
  ,CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 1, 1) + '%' THEN '' ELSE SUBSTRING(x, 1, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 2, 1) + '%' THEN '' ELSE SUBSTRING(x, 2, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 3, 1) + '%' THEN '' ELSE SUBSTRING(x, 3, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 4, 1) + '%' THEN '' ELSE SUBSTRING(x, 4, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 5, 1) + '%' THEN '' ELSE SUBSTRING(x, 5, 1) END
    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 6, 1) + '%' THEN '' ELSE SUBSTRING(x, 6, 1) END
-- Keep adding rows until you reach the column size 
    AS stripped_column
FROM (SELECT 
        column_to_strip AS x
        ,'ABCDEFGHIJKLMNOPQRSTUVWXYZ' AS a 
      FROM my_table) a

이 방법을 사용하면 하위 쿼리의 한 문자열에 유효한 문자가 포함되어 다른 문자 집합을 쉽게 재구성 할 수 있다는 이점이 있습니다.

단점은 각 문자에 대해 열 크기까지 SQL 행을 추가해야한다는 것입니다. 이 작업을 쉽게하기 위해 아래의 Powershell 스크립트를 사용했습니다.

1..64 | % {
  "    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, {0}, 1) + '%' THEN '' ELSE SUBSTRING(x, {0}, 1) END" -f $_
} | clip.exe

3
일반적으로 어색하지만 열이 좁은 일회용 쿼리에는 쉽고 유용합니다.
Eric J.

3

다음을 사용하여 알파벳이 아닌 문자를 제거하는 다른 방법이 iTVF있습니다. 먼저 패턴 기반 문자열 스플리터가 필요합니다. 다음은 Dwain Camp의 기사 에서 가져온 것입니다 .

-- PatternSplitCM will split a string based on a pattern of the form 
-- supported by LIKE and PATINDEX 
-- 
-- Created by: Chris Morris 12-Oct-2012 
CREATE FUNCTION [dbo].[PatternSplitCM]
(
       @List                VARCHAR(8000) = NULL
       ,@Pattern            VARCHAR(50)
) RETURNS TABLE WITH SCHEMABINDING 
AS 

RETURN
    WITH numbers AS (
        SELECT TOP(ISNULL(DATALENGTH(@List), 0))
            n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
        FROM
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
        (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n)
    )

    SELECT
        ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)),
        Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)),
        [Matched]
    FROM (
        SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n)
        FROM numbers
        CROSS APPLY (
            SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END
        ) y
    ) d
    GROUP BY [Matched], Grouper

이제 패턴 기반 스플리터가 있으므로 패턴과 일치하는 문자열을 분할해야합니다.

[a-z]

그런 다음 원하는 결과를 얻기 위해 다시 연결하십시오.

SELECT *
FROM tbl t
CROSS APPLY(
    SELECT Item + ''
    FROM dbo.PatternSplitCM(t.str, '[a-z]')
    WHERE Matched = 1
    ORDER BY ItemNumber
    FOR XML PATH('')
) x (a)

견본

결과:

| Id |              str |              a |
|----|------------------|----------------|
|  1 |    testte d'abc |     testtedabc |
|  2 |            anr¤a |           anra |
|  3 |  gs-re-C“te d'ab |     gsreCtedab |
|  4 |         Mfe, DF |          MfeDF |
|  5 |           Rtemd |          Rtemd |
|  6 |          jadji |          jadji |
|  7 |      Cje y ret¢n |       Cjeyretn |
|  8 |        Jklbalu |        Jklbalu |
|  9 |       lene-iokd |       leneiokd |
| 10 |   liode-Pyrnie |    liodePyrnie |
| 11 |         Vs Gta |          VsGta |
| 12 |        Sƒo Paulo |        SoPaulo |
| 13 |  vAstra gAtaland | vAstragAtaland |
| 14 |  ¥uble / Bio-Bio |     ubleBioBio |
| 15 | Upln/ds VAsb-y |    UplndsVAsby |

다른 답변보다 이것을 사용하면 어떤 이점이 있습니까?
S.Serpooshan

2

Allen의 솔루션에서 영감을 얻은이 솔루션 Numbers에는 정수 테이블이 필요합니다 (좋은 성능으로 심각한 쿼리 작업을 수행하려는 경우 보유해야 함). CTE가 필요하지 않습니다. NOT IN (...)특정 문자를 제외 하도록 표현식을 변경하거나 특정 문자 만 유지 하도록 IN (...)OR LIKE표현식으로 변경할 수 있습니다.

SELECT (
    SELECT  SUBSTRING([YourString], N, 1)
    FROM    dbo.Numbers
    WHERE   N > 0 AND N <= CONVERT(INT, LEN([YourString]))
        AND SUBSTRING([YourString], N, 1) NOT IN ('(',')',',','.')
    FOR XML PATH('')
) AS [YourStringTransformed]
FROM ...

관련없는 문제에 대한 흥미로운 해결책.
TaterJuice

2

다음은 함수를 만들거나 대체 할 모든 문자 인스턴스를 나열 할 필요가없는 솔루션입니다. 원치 않는 문자를 찾기 위해 PATINDEX와 함께 재귀 WITH 문을 사용합니다. 주어진 문자열에 포함 된 최대 100 개의 고유 한 잘못된 문자-열에서 원하지 않는 모든 문자를 대체합니다. (EG "ABC123DEF234"는 1, 2, 3 및 4의 잘못된 문자 4 개를 포함합니다.) 100 제한은 WITH 문에 허용되는 최대 재귀 수이지만 처리 할 행 수에 제한을 두지는 않습니다. 사용 가능한 메모리에 의해서만 제한됩니다.
DISTINCT 결과를 원하지 않으면 코드에서 두 가지 옵션을 제거 할 수 있습니다.

-- Create some test data:
SELECT * INTO #testData 
FROM (VALUES ('ABC DEF,K.l(p)'),('123H,J,234'),('ABCD EFG')) as t(TXT)

-- Actual query:
-- Remove non-alpha chars: '%[^A-Z]%'
-- Remove non-alphanumeric chars: '%[^A-Z0-9]%'
DECLARE @BadCharacterPattern VARCHAR(250) = '%[^A-Z]%';

WITH recurMain as (
    SELECT DISTINCT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex
    FROM #testData
    UNION ALL
    SELECT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex
    FROM (
        SELECT 
            CASE WHEN BadCharIndex > 0 
                THEN REPLACE(TXT, SUBSTRING(TXT, BadCharIndex, 1), '')
                ELSE TXT 
            END AS TXT
        FROM recurMain
        WHERE BadCharIndex > 0
    ) badCharFinder
)
SELECT DISTINCT TXT
FROM recurMain
WHERE BadCharIndex = 0;

1

나는 PatIndex가 호출되는 두 곳에 두었다.

PatIndex('%[^A-Za-z0-9]%', @Temp)

RemoveNonAlphaCharacters 위의 사용자 정의 함수의 이름을 RemoveNonAlphaNumericCharacters로 변경했습니다.


1

-먼저 하나의 함수를 만듭니다

CREATE FUNCTION [dbo].[GetNumericonly]
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
     DECLARE @intAlpha INT
     SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
     WHILE @intAlpha > 0
   BEGIN
          SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
          SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric )
   END
END
RETURN ISNULL(@strAlphaNumeric,0)
END

이제이 함수를 다음과 같이 호출하십시오.

select [dbo].[GetNumericonly]('Abhi12shek23jaiswal')

결과는 다음과 같습니다

1223

1

성능 관점에서 인라인 함수를 사용합니다.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[udf_RemoveNumericCharsFromString]
(
@List NVARCHAR(4000)
)
RETURNS TABLE 
AS RETURN

    WITH GetNums AS (
       SELECT TOP(ISNULL(DATALENGTH(@List), 0))
        n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
        FROM
          (VALUES (0),(0),(0),(0)) d (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n),
          (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n)
            )

    SELECT StrOut = ''+
        (SELECT Chr
         FROM GetNums
            CROSS APPLY (SELECT SUBSTRING(@List , n,1)) X(Chr)
         WHERE Chr LIKE '%[^0-9]%' 
         ORDER BY N
         FOR XML PATH (''),TYPE).value('.','NVARCHAR(MAX)')


   /*How to Use
   SELECT StrOut FROM dbo.udf_RemoveNumericCharsFromString ('vv45--9gut')
   Result: vv--gut
   */

나는이 스레드가 오래되었다는 것을 알고 있지만 인라인 테이블 반환 함수가 길입니다. '.'), TYPE) .value를 ( 'NVARCHAR (MAX)가')이 필요하지 않고 ~ 50 % 아래로 기능이 저하됩니다 솔루션에 대한 문제는 당신 만이 코드를 숫자를 반환하고 있기 때문에,이다
Alan Burstein

1

@Gerhard Weiss의 답변을 기반으로 한 또 다른 재귀 CTE 솔루션이 있습니다 . 전체 코드 블록을 복사하여 SSMS에 붙여 넣을 수 있습니다. 결과에는 진행 상황을 이해하는 데 도움이되는 몇 가지 추가 열이 포함됩니다. PATINDEX (RegEx)와 재귀 CTE에서 일어나는 모든 것을 이해할 때까지 시간이 걸렸습니다.

DECLARE @DefineBadCharPattern varchar(30)
SET @DefineBadCharPattern = '%[^A-z]%'  --Means anything NOT between A and z characters (according to ascii char value) is "bad"
SET @DefineBadCharPattern = '%[^a-z0-9]%'  --Means anything NOT between a and z characters or numbers 0 through 9 (according to ascii char value) are "bad"
SET @DefineBadCharPattern = '%[^ -~]%'  --Means anything NOT between space and ~ characters (all non-printable characters) is "bad"
--Change @ReplaceBadCharWith to '' to strip "bad" characters from string
--Change to some character if you want to 'see' what's being replaced. NOTE: It must be allowed accoring to @DefineBadCharPattern above
DECLARE @ReplaceBadCharWith varchar(1) = '#'  --Change this to whatever you want to replace non-printable chars with 
IF patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, @ReplaceBadCharWith) > 0
    BEGIN
        RAISERROR('@ReplaceBadCharWith value (%s) must be a character allowed by PATINDEX pattern of %s',16,1,@ReplaceBadCharWith, @DefineBadCharPattern)
        RETURN
    END
--A table of values to play with:
DECLARE @temp TABLE (OriginalString varchar(100))
INSERT @temp SELECT ' 1hello' + char(13) + char(10) + 'there' + char(30) + char(9) + char(13) + char(10)
INSERT @temp SELECT '2hello' + char(30) + 'there' + char(30)
INSERT @temp SELECT ' 3hello there'
INSERT @temp SELECT ' tab' + char(9) + ' character'
INSERT @temp SELECT 'good bye'

--Let the magic begin:
;WITH recurse AS (
    select
    OriginalString,
    OriginalString as CleanString,
    patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString) as [Position],
    substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1) as [InvalidCharacter],
    ascii(substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1)) as [ASCIICode]
    from @temp
   UNION ALL
    select
    OriginalString,
    CONVERT(varchar(100),REPLACE(CleanString,InvalidCharacter,@ReplaceBadCharWith)),
    patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) as [Position],
    substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1),
    ascii(substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1))
    from recurse
    where patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) > 0
)
SELECT * FROM recurse
--optionally comment out this last WHERE clause to see more of what the recursion is doing:
WHERE patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) = 0

0

CTE 생성 숫자 테이블을 사용하여 각 문자를 검사 한 다음 FOR XML을 사용하여 유지할 수있는 값의 문자열에 연결할 수 있습니다.

CREATE FUNCTION [dbo].[PatRemove](
    @pattern varchar(50),
    @expression varchar(8000) 
    )
RETURNS varchar(8000)
AS
BEGIN
    WITH 
        d(d) AS (SELECT d FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) digits(d)),
        nums(n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM d d1, d d2, d d3, d d4),
        chars(c) AS (SELECT SUBSTRING(@expression, n, 1) FROM nums WHERE n <= LEN(@expression))
    SELECT 
        @expression = (SELECT c AS [text()] FROM chars WHERE c NOT LIKE @pattern FOR XML PATH(''));

    RETURN @expression;
END

0
DECLARE @vchVAlue NVARCHAR(255) = 'SWP, Lettering Position 1: 4 Ω, 2: 8 Ω, 3: 16 Ω, 4:  , 5:  , 6:  , Voltage Selector, Solder, 6, Step switch, : w/o fuseholder '


WHILE PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))) > 0
  BEGIN
    SELECT @vchVAlue = STUFF(@vchVAlue,PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))),1,' ')
  END 

SELECT @vchVAlue

0

아랍어 문자를 유지하려고 할 때이 방법은 저에게 효과적이지 않았습니다. 정규 표현식을 대체하려고 시도했지만 작동하지 않았습니다. ASCII 레벨에서 작동하는 또 다른 방법을 작성했으며 그것이 유일한 선택이었습니다.

 Create function [dbo].[RemoveNonAlphaCharacters] (@s varchar(4000)) returns varchar(4000)
   with schemabinding
begin
   if @s is null
      return null
   declare @s2 varchar(4000)
   set @s2 = ''
   declare @l int
   set @l = len(@s)
   declare @p int
   set @p = 1
   while @p <= @l begin
      declare @c int
      set @c = ascii(substring(@s, @p, 1))
      if @c between 48 and 57 or @c between 65 and 90 or @c between 97 and 122 or @c between 165 and 253 or @c between 32 and 33
         set @s2 = @s2 + char(@c)
      set @p = @p + 1
      end
   if len(@s2) = 0
      return null
   return @s2
   end

가다


-1

게시물이 약간 오래되었지만 다음과 같이 말하고 싶습니다. 위의 솔루션에서 겪었던 문제는 ç, ë, ï 등과 같은 문자를 필터링하지 않는다는 것입니다. 다음과 같이 기능을 조정했습니다 (메모리를 절약하기 위해 80 varchar 문자열 만 사용했습니다).

create FUNCTION dbo.udf_Cleanchars (@InputString varchar(80)) 
RETURNS varchar(80) 
AS 

BEGIN 
declare @return varchar(80) , @length int , @counter int , @cur_char char(1) 
SET @return = '' 
SET @length = 0 
SET @counter = 1 
SET @length = LEN(@InputString) 
IF @length > 0 
BEGIN WHILE @counter <= @length 

BEGIN SET @cur_char = SUBSTRING(@InputString, @counter, 1) IF ((ascii(@cur_char) in (32,44,46)) or (ascii(@cur_char) between 48 and 57) or (ascii(@cur_char) between 65 and 90) or (ascii(@cur_char) between 97 and 122))
BEGIN SET @return = @return + @cur_char END 
SET @counter = @counter + 1 
END END 

RETURN @return END

고마워, 에릭 당신이 말했듯이, 답변으로 표시된 게시물은 매우 좋지만, 1/2와 같은 구피적인 "숫자"문자는 제거하지 않습니다.
troy jan

-3

방금 Oracle 10g에 내장되어 있음을 발견했습니다. 전화 번호 비교를 위해 모든 특수 문자를 제거해야했습니다.

regexp_replace(c.phone, '[^0-9]', '')

5
"SQL Server"는 특히 Microsoft 제품을 나타냅니다.
아무도
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.