列の特殊文字をスペースで置き換える


10

特殊文字をスペースに置き換えるクエリを作成しようとしています。以下のコードは、行を識別するのに役立ちます。(英数字、カンマ、スペースは有効です):

SELECT columnA
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'

置換関数をselectステートメントに統合して、結果セット内の英数字、コンマ、スペース以外のすべての文字を ''(スペース)で置き換えるにはどうすればよいですか。これは機能しません:

SELECT replace(columnA,'%[^a-Z0-9, ]%',' ')
FROM tableA
WHERE columnA like '%[^a-Z0-9, ]%'

回答:


11

米国英語のアルファベット(大文字と小文字の両方のバージョン)の26文字のみを使用することが保証されている場合は、確かに、使用LIKEしたりPATINDEX、簡単な範囲表記[a-z](または、大文字と小文字を区別しない照合を使用する場合は、大文字の「Z」を使用する必要があります)。

ただし、en-USアルファベットにはない文字がVARCHARデータのさまざまなコードページ/照合で利用できる場合(例Þ=ラテン大文字 "Thorn" = SELECT CHAR(0xDE))、その文字クラスに含める必要がある場合があります[a-z0-9, Þ]。もちろん、これらの余分な文字はコードページごとです。

また、照合タイプ(SQL ServerとWindows)と感度の設定(大文字と小文字、アクセントなど、大文字と小文字を区別)は、特定の範囲に含まれる文字に影響することに注意してください。たとえば、SQL Server照合順序は、大文字と小文字をWindows照合順序とは逆の順序で並べ替えます。AaBb...つまり、両方の種類の照合で大文字と小文字が区別される照合を想定すると、一方が実行され、もう一方が実行されますaAbB...。その効果は、一方のa範囲内にありA-Z、もう一方の範囲内にはありません。そして、の範囲は、a-Zバイナリ照合(のいずれかで終わる1内の任意の文字と一致していないだろう_BIN_BIN2、しかし使わない_BINの値が与えられたことを)A65で、aは97なので、97から65の無効な範囲です;-)。バリエーションが多すぎてここでの例を示すことができないので、近いうちにブログに詳細な説明を投稿するつもりです(それから、これへのリンクでこれを更新します)。ただし、他の言語から有効な文字を取得する場合でも、米国英語の文字のみを受け入れることに厳格になる場合は、おそらく次のパターン照合順序を使用することをお勧めします。

LIKE '%[^A-Za-z0-9, ]%' COLLATE Latin1_General_100_BIN2

NVARCHARデータをサポートしていて、さまざまな言語から「単語」文字を取得できる場合、T-SQLはこれらを区別するための実際の方法がないため、あまり役に立ちません。この場合、正規表現(RegEx)、具体的にはReplaceメソッド/関数を使用する必要があります。これらはSQLCLRを通じてのみ使用できます。以下は、いくつかの「特殊」文字を置き換えるが、少なくとも1つの言語で有効な文字をすべて残す例を示しています。

DECLARE @Test NVARCHAR(500);
SET @Test = N'this$is%a<>TEST,;to}⌡↕strip╞╟╚══¶out_ç_ƒ▀ special-ij-೫-chars-舛-დ-א-B';
SELECT SQL#.RegEx_Replace4k(@Test, N'[\W\p{Pc}-[,]]', N' ', -1, 1, NULL); 

戻り値:

this is a  TEST, to   strip      out ç ƒ  special ij ೫ chars 舛 დ א B

RegEx式の意味は次のとおりです。

  • \W=「単語以外の文字」を意味するRegEx「エスケープ」
  • \p{Pc}=「句読点、コネクタ」のUnicode「カテゴリ」(この「カテゴリ」は\Wエスケープによって明確に除外されているため、これは一致にのみ必要)
  • -[,]=クラスの減算(これは、\Wエスケープに含まれているため、「特殊」としてコンマをマッチングから除外するために必要です)

次のコマンドを発行するだけで、テーブルを更新できます。

UPDATE tbl
SET    tbl.field = SQL#.RegEx_Replace4k(tbl.field, N'[\W\p{Pc}-[,]]', N' ', -1, 1, NULL)
FROM   tbl
WHERE  SQL#.RegEx_IsMatch4k(tbl.field, N'[\W\p{Pc}-[,]]', 1, NULL) = 1;

これらの例では、私が作成したSQLCLR関数の無料バージョンSQL#ライブラリで使用可能な2つの関数を使用したことに注意してください(ただし、これらも無料です)。またNVARCHAR(4000)NVARCHAR(MAX)パラメータタイプの代わりに使用するため、より高速な「4k」バージョンを使用したことにも注意してください。データがを使用している場合はNVARCHAR(MAX)、関数名から「4k」を削除するだけです。

こちらもご覧ください:


5

私はここに似ようなことをする投稿を持っています

基本的に、私は再帰CTEを使用してループを何度も繰り返し、一度に1つの「悪い」文字を置き換えています。STUFFを使用して1文字(スペースで置き換えることができます)を削除し、PATINDEXを使用して削除する文字の場所を見つけています。あなたが探していることをするために少し修正することができます。ただし、「良い」リストが作成され、実際には既存のリストは更新されません。

DECLARE @Pattern varchar(50) = '%[^A-Za-z0-9, ]%';

WITH FixBadChars AS (SELECT StringToFix, StringToFix AS FixedString, 1 AS MyCounter, Id
                FROM BadStringList
                UNION ALL
                SELECT StringToFix, Stuff(FixedString, PatIndex(@Pattern, 
                    FixedString COLLATE Latin1_General_BIN2), 1, ' ') AS FixedString, 
                    MyCounter + 1, Id
                FROM FixBadChars
                WHERE FixedString COLLATE Latin1_General_BIN2 LIKE @Pattern)
SELECT StringToFix, FixedString, MyCounter, Id
FROM FixBadChars
WHERE MyCounter = 
        (SELECT MAX(MyCounter) 
        FROM FixBadChars Fixed
        WHERE Fixed.Id = FixBadChars.Id)
OPTION (MAXRECURSION 1000);

クエリだけでなく更新を行うために下部を変更できるはずですが、実際には試していません。私はそれがこのようなものになるだろうとかなり確信しています:

UPDATE FixBadChars
SET StringToFix = FixedString
WHERE MyCounter = 
        (SELECT MAX(MyCounter) 
        FROM FixBadChars Fixed
        WHERE Fixed.Id = FixBadChars.Id)
OPTION (MAXRECURSION 1000);

スケーラビリティに関する限り、30秒以内に約17万行のクリーンな行を返しました。もう一度、更新を行うかどうかはわかりませんが、これは私のラップトップでしたが、6GBのRAMでかなり遅くなります。


0
Declare @String nchar(2000)='hg$%^AB,.:23ab-=+'

Declare @NewString VARCHAR(2000)=''
Declare @Lenght int=LEN(@String)
Declare @Index int=1

WHILE (@Index <= @Lenght)
BEGIN
    Declare @Letter nchar(1)=Substring(@String,@Index,1);
    Declare @ASCII int=ASCII(@Letter);
    If((@ASCII >= 48 and @ASCII <= 57) or (@ASCII >= 97 and @ASCII <= 122) or (@ASCII >= 65 and @ASCII <= 90))
    BEGIN
        SET @NewString += @Letter
    END
    ELSE
    BEGIN
        SET @NewString += ' '
    END
    SET @Index+=1

END
Select @NewString
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.