代码之家  ›  专栏  ›  技术社区  ›  Even Mien

如何在SQL Server中从字符串中删除所有非字母字符?

  •  151
  • Even Mien  · 技术社区  · 17 年前

    非字母数字的呢?

    这必须是一个自定义函数还是有更多的通用解决方案?

    19 回复  |  直到 17 年前
        1
  •  392
  •   George Mastros    12 年前

    尝试此功能:

    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')
    

    一旦您理解了代码,您应该会发现将其更改为删除其他字符也相对简单。您甚至可以将此动态设置为足以在搜索模式中传递。

    希望能有帮助。

        2
  •  190
  •   Even Mien    5 年前

    的参数化版本 George Mastros ' awesome answer :

    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
  •  9
  •   J Brun    9 年前

    信不信由你,在我的系统中,这个丑陋的函数比优雅的函数表现得更好。

    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
    
        4
  •  6
  •   Rob Garrison    17 年前

    我知道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
    

    第二轮-数据驱动黑名单

    -- ============================================
    -- 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
    

    我对读者的挑战:你能让这更有效吗?使用递归怎么样?

        5
  •  5
  •   Graeme Job    11 年前

    这里的解决方案不需要创建函数或列出所有要替换的字符实例。它结合使用递归WITH语句和PATINDEX来查找不需要的字符。它将替换一列中所有不需要的字符-任何给定字符串中最多包含100个唯一的坏字符。(例如,“ABC123DEF234”将包含4个错误字符1、2、3和4)100限制是WITH语句中允许的最大递归数,但这不会对要处理的行数施加限制,这仅受可用内存的限制。
    如果不希望得到不同的结果,可以从代码中删除这两个选项。

    -- 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;
    
        6
  •  4
  •   Kyle Hale    12 年前

    如果您和我一样,没有向生产数据添加函数的权限,但仍然希望执行这种过滤,那么这里有一个纯SQL解决方案,使用透视表将过滤后的部分重新组合在一起。

    请注意

    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
    
        7
  •  4
  •   Dave Sexton    11 年前

    查看了所有给定的解决方案后,我认为必须有一个纯SQL方法,它不需要函数或CTE/XML查询,并且不涉及难以维护的嵌套REPLACE语句。以下是我的解决方案:

    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
    

    这样做的好处是,有效字符包含在子查询的一个字符串中,便于为不同的字符集重新配置。

    1..64 | % {
      "    + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, {0}, 1) + '%' THEN '' ELSE SUBSTRING(x, {0}, 1) END" -f $_
    } | clip.exe
    
        8
  •  3
  •   Felix Pamittan    10 年前

    下面是使用 iTVF . 首先,需要一个基于模式的字符串拆分器。这是一张从德文营地拍的 article :

    -- 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)
    

    SAMPLE

    结果:

    | Id |              str |              a |
    |----|------------------|----------------|
    |  1 |    test“te d'abc |     testtedabc |
    |  2 |            anr¤a |           anra |
    |  3 |  gs-re-C“te d'ab |     gsreCtedab |
    |  4 |         M‚fe, DF |          MfeDF |
    |  5 |           R™temd |          Rtemd |
    |  6 |          ™jad”ji |          jadji |
    |  7 |      Cje y ret¢n |       Cjeyretn |
    |  8 |        J™kl™balu |        Jklbalu |
    |  9 |       le“ne-iokd |       leneiokd |
    | 10 |   liode-Pyr‚n‚ie |    liodePyrnie |
    | 11 |         V„s G”ta |          VsGta |
    | 12 |        Sƒo Paulo |        SoPaulo |
    | 13 |  vAstra gAtaland | vAstragAtaland |
    | 14 |  ¥uble / Bio-Bio |     ubleBioBio |
    | 15 | U“pl™n/ds VAsb-y |    UplndsVAsby |
    
        9
  •  2
  •   Jay Bienvenu    11 年前

    受艾伦先生的解决方案启发,这个解决方案需要 Numbers 整数表(如果您想以良好的性能执行严肃的查询操作,您应该手头有这个表)。它不需要CTE。你可以换个房间 NOT IN (...) 表达式以排除特定字符,或将其更改为 IN (...) 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 ...
    
        10
  •  2
  •   Baodad    8 年前

    here . 您应该能够将整个代码块复制并粘贴到SSM中,并在那里使用它。结果包括一些额外的专栏,以帮助我们了解发生了什么。我花了一段时间才理解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
    
        11
  •  1
  •   user381460    14 年前

    我把这个放在两个叫PatIndex的地方。

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

    用于上面的自定义函数RemovenonalPharacters,并将其重命名为RemoveNonAlphaNumericCharacters

        12
  •  1
  •   Abhishek Jaiswal    10 年前

    --首先创建一个函数

    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
    
        13
  •  1
  •   hkravitz    9 年前

    从性能角度来看,我会使用内联函数:

    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
       */
    
        14
  •  1
  •   Zhorov    5 年前

    SQL Server 2017+的另一个可能选项是使用 TRANSLATE() REPLACE() .

    DECLARE @pattern varchar(52) = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    
    SELECT 
       v.[Text], 
       REPLACE(
          TRANSLATE(
             v.[Text],
             REPLACE(TRANSLATE(v.[Text], @pattern, REPLICATE('a', LEN(@pattern))), 'a', ''),
             REPLICATE('0', LEN(REPLACE(TRANSLATE(v.[Text], @pattern, REPLICATE('a', LEN(@pattern))), 'a', '')))
          ),
          '0',
          ''
       ) AS AlphabeticCharacters
    FROM (VALUES
       ('abc1234def5678ghi90jkl#@$&'),
       ('1234567890'),
       ('JAHDBESBN%*#*@*($E*sd55bn')
    ) v ([Text])
    

    或者作为一种功能:

    CREATE FUNCTION dbo.RemoveNonAlphabeticCharacters (@Text varchar(1000)) 
    RETURNS varchar(1000)
    AS BEGIN
    
       DECLARE @pattern varchar(52) = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
       SET @text = REPLACE(
          TRANSLATE(
             @Text,
             REPLACE(TRANSLATE(@Text, @pattern, REPLICATE('a', LEN(@pattern))), 'a', ''),
             REPLICATE('0', LEN(REPLACE(TRANSLATE(@Text, @pattern, REPLICATE('a', LEN(@pattern))), 'a', '')))
          ),
          '0',
          ''
       )
       
       RETURN @Text
    END
    
        15
  •  1
  •   MarianoC    5 年前

    对于SQL Server>=2017...

    declare @text varchar(max)
    
    -- create some sample text
    select
    @text=
    '
    Lorem @ipsum  *&dolor-= sit?! amet, {consectetur } adipiscing\ elit. Vivamus commodo justo metus, sed facilisis ante 
    congue eget. Proin ac bibendum sem/.
    '
    
    -- the characters to be removed
    declare @unwanted varchar(max)='''.,!?/<>"[]{}|`~@#$%^&*()-+=/\:;'+char(13)+char(10)
    
    -- interim replaced with
    declare @replace_with char(1)=' '
    
    -- call the translate function that will change unwanted characters to spaces
    -- in this sample
    declare @translated varchar(max)
    select @translated=TRANSLATE(@text,@unwanted,REPLICATE(@replace_with,len(@unwanted)))
    
    -- In this case, I want to preserve one space
    select  string_agg(trim(value),' ')
    from    STRING_SPLIT(@translated,' ')
    where   trim(value)<>''
    
    -- Result
    'Lorem ipsum dolor sit amet consectetur adipiscing elit Vivamus commodo justo metus sed facilisis ante congue eget Proin ac bibendum sem'
    
        16
  •  0
  •   Dennis Allen    12 年前

    使用CTE生成的数字表检查每个字符,然后将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
    
        17
  •  0
  •   toha    9 年前
    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
    
        18
  •  0
  •   AGM    9 年前

    这种方法对我不起作用,因为我试图保留阿拉伯字母,我试图替换正则表达式,但也不起作用。我写了另一个方法在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
    

        19
  •  -1
  •   Eric    10 年前

    虽然这篇文章有点陈旧,但我想说以下几点。 我使用上述解决方案时遇到的问题是,它无法过滤掉§、、等字符。我对函数进行了如下调整(我只使用了一个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
    
        20
  •  -3
  •   Lu_Bu    12 年前

    如果您正在使用Oracle 10g,我刚刚发现它内置于Oracle 10g中。为了比较电话号码,我不得不去掉所有的特殊字符。

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