Як зняти всі не алфавітні символи з рядка в SQL Server?


Відповіді:


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 Ця рядок пошуку відображається в коді в двох різних місцях. Обов’язково замініть їх обох.
Джордж Мастрос

26
З коментаря Джеффа: Я думаю, що якби хотілося зняти всі не букви та не цифри, ви хочете, щоб '^ a-z0-9' (проти '^ az ^ 0-9', який залишив ^ у рядку) .
Навіть Мієн

1
+1 Джордж. Це одне з тих місць, де "встановлений на основі" код і використання вбудованих скалярних функцій мають великі труднощі при побитті рядка за рядком. Чудово зроблено. Також я вже пару років використовую функцію "Початкові шапки", яка має ту саму основну форму.
Джефф Моден

6
@Lynchie Змінення '% [^ az]%' До '% [^ az]%' В основному просто поставте пробіл після z.
Джордж Мастрос

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, перш ніж прокручувати вниз, щоб проголосувати за неї!
заробіток

Шаблон регулярного виразів, здається, не працює з усім пробілом. Якщо я хочу позбавити всіх спеціальних символів, окрім буквено-цифрових символів та пробілів, я б очікував використовувати SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9\s')пробіли, які все ще знімають пробіл. Я також намагався використовувати, [[:blank:]]але це порушує функцію, і нічого не видаляється з рядка. Найближчий Ive отриманий за допомогою: SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^a-z0-9 ')(жорсткого кодування пробілу в шаблоні регулярних виразів). Однак це не усуває розриви рядків.
Біллі Маккі

2
@BillyMcKee Додайте пробіл на початку, а не додайте його в кінці регулярного виразу. SELECT dbo.fn_StripCharacters('a1!s2 spaces @d3# f4$', '^ a-z0-9')
Майк

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

як щодо загальних коми, періодів, простору тощо?
соїм

наскільки різняться, якщо ви не використовуєте 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

Додайте СЕМЕЙНІСТЬ до його функції, як і ваша функція. Ви використовуєте VARCHAR, його функція використовує NVARCHAR. Якщо параметри, які ви передаєте на його функцію VARCHAR, вам слід використовувати VARCHAR замість NVARCHAR в межах його функції в іншому випадку, вашій системі потрібно буде передати рядкові значення з 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

Моє завдання читачам: чи можете ви зробити це більш ефективним? Що з використанням рекурсії?


ви, можливо, могли б написати кращий dbo.StripBlacklistCharacters () без циклу, використовуючи sommarskog.se/arrays-in-sql-2005.html#tblnum таблицю чисел, приєднаних до вашої таблиці чорного списку, але я сьогодні дуже лінивий, щоб спробувати це сам ....
КМ.

4

Якщо ви схожі на мене і не маєте доступу просто додавати функції до своїх виробничих даних, але все ще хочете виконати такий тип фільтрації, ось чисте рішення SQL, використовуючи таблицю PIVOT, щоб знову відфільтрувати відфільтровані фрагменти.

Примітка: Я жорстко кодував таблицю до 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

Це рішення було для мене в 2,3 рази швидшим, ніж використання функції на наборі в 235 К рядків. Я також повинен був зробити дві заміни і використав загалом чотири CTE. Працював як чемпіон.
JJS

4

Переглянувши всі наведені рішення, я подумав, що повинен бути чистий метод 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

Перевагою цього способу є те, що дійсні символи містяться в одній рядку в підзапиті, що дозволяє легко переналаштувати для іншого набору символів.

Мінус полягає в тому, що вам потрібно додати рядок SQL для кожного символу до розміру стовпця. Щоб полегшити це завдання, я просто використав сценарій Powershell нижче, цей приклад, якщо для VARCHAR (64):

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

3
Незручний у загальному випадку, але простий та корисний для одноразового запиту із вузьким стовпцем.
Ерік Дж.

3

Ось ще один спосіб видалити неабетичні символи за допомогою iTVF. По-перше, вам потрібен подільник струн на основі шаблону. Ось один із положень статті Двен Кемп :

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

Це рішення, натхнене рішенням містера Аллена, вимагає 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 ...

Цікаве вирішення непов'язаного питання.
TaterJuice

2

Ось рішення, яке не потребує створення функції або переліку всіх примірників символів для заміни. Він використовує рекурсивний оператор WITH у поєднанні з PATINDEX для пошуку небажаних символів. Він замінить усі небажані символи в стовпці - до 100 унікальних поганих символів, що містяться в будь-якому даному рядку. (EG "ABC123DEF234" міститиме 4 поганих символи 1, 2, 3 і 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%
Алан Бурштейн

1

Ось ще одне рекурсивне рішення CTE, засноване на відповіді @Gerhard Weiss тут . Ви повинні мати можливість скопіювати і вставити весь блок коду в 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 таблиць для вивчення кожного символу, а потім ДЛЯ 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

Хоча посада трохи стара, я хотів би сказати наступне. Проблема, яку я мав з вищевказаним рішенням, полягає в тому, що вона не фільтрує такі символи, як ç, ë, ï тощо.

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

Дякую за це, Еріку. Як ви кажете, відповідь, позначена публікацією, є дуже хорошою, але вона не позбавляє тупіх "числових" символів, як ½.
troy

-3

Я щойно знайшов це вбудованим у Oracle 10g, якщо саме це ви використовуєте. Мені довелося зняти всіх спеціальних символів для порівняння номера телефону.

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

5
"SQL Server" стосується конкретно продукту Microsoft.
ніхто
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.