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に置き換えます。この検索文字列は、コードの2つの異なる場所に表示されます。必ず両方を交換してください。
ジョージ・マストロス2009年

26
ジェフのコメントから:すべての非文字と非数値を削除したい場合は、「^ a-z0-9」が必要です(「^ az ^ 0-9」ではなく、文字列に^が残ります)。 。
Mienでさえ2010

1
+1ジョージ。これは、「セットベース」のコードとインラインスカラー関数の使用が行ごとの比較で非常に困難な場所の1つです。よくできました。また、基本的な形が同じ「イニシャルキャップ」機能を数年間使用しています。
Jeff Moden

6
@Lynchie Change '%[^ az]%' to '%[^ az]%'基本的には、zの後にスペース文字を置くだけです。
George Mastros 14

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の回答の私の適応を作成しました!
アーンシャビアン11/11 / 15、11:

正規表現パターンは、すべての空白で機能するとは限りません。英数字と空白以外のすべての特殊文字を削除したい場合は、空白を削除すること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

一般的なコンマ、ピリオド、スペースなどはどうですか?
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()を書くことができますが 、今日私はそれを試すのが面倒です私自身....
和基。

4

私のようで、本番データに関数を追加するだけのアクセス権がなく、この種のフィルタリングを実行したい場合は、PIVOTテーブルを使用して、フィルタリングされたピースを再び元に戻す純粋なSQLソリューションを次に示します。

注意:テーブルを最大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 2014

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

この方法を使用する利点は、有効な文字がサブクエリの1つの文字列に含まれているため、別の文字セットを簡単に再構成できることです。

欠点は、列のサイズまで、文字ごとに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
一般的なケースでは厄介ですが、列が狭い場合の1回限りのクエリには簡単で便利です。
エリックJ.

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 2018

2

アレン氏のソリューションに着想を得たこのソリューションには、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"には4つの不正な文字1、2、3、および4が含まれます)100の制限はWITHステートメントで許可される再帰の最大数ですが、これは処理する行数に制限を課しません。利用可能なメモリによってのみ制限されます。
DISTINCTの結果が必要ない場合は、コードから2つのオプションを削除できます。

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

-まず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%遅くします
アランバーシュタイン2017年

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

これをありがとう、エリック。あなたが言うように、回答とマークされた投稿は非常に良いですが、½のような間抜けな「数字」文字を取り除きません。
2016年

-3

私が使用しているのがOracle 10gに組み込まれている場合です。電話番号を比較するために、特殊文字をすべて取り除く必要がありました。

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

5
「SQL Server」とは、特にMicrosoft製品を指します。
誰も
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.