[0-9]は数字、[az]は文字のように、句読点に相当するT-SQLはありますか?


8

句読点を含む列から値をプルできるようにする[0-9]および[a-z]パターンに相当するT-SQLはありますか?

例えば:

Create Table #Test
(
Value   VarChar(10)
) 
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')

Select      *
From        #Test
Where       Value like '[0-9][0-9][0-9][a-z]'

これは、最初の3文字が0から9までの数字で、最後の文字がaからzまでの文字である値を返すため、123aおよびなど456bの値を返しますが、の値は返しません12ABC

句読点に相当するもの[0-9]が数字や[a-z]文字にあるかどうか知りたいので、返さAB!23C?D789ますか?

正規表現を使用できる場合^[a-zA-Z0-9]*$、文字列内の英数字に一致する表現を使用する可能性があります。

Where       Value like '^[a-zA-Z0-9]*$'

これに相当するSQLはありますか?

RegExで実行できるこの種のことは知っていますが、T-SQLでそれが必要です。このサーバーにカスタムアセンブリをロードできないため、正規表現を使用できません。

実際の列はvarchar(200)です。照合順序は、Latin1_General_CI_ASです。SQL Server 2012 Standard Editionを使用しています。


回答:


12

正確なソリューションに到達する際の最大の困難は、どの文字を含める(または除外するか、どちらの方向が操作に意味があるか)を正確に定義することです。意味:

  • 私たちは話しているVARCHAR/ ASCIIデータまたはNVARCHAR/ Unicodeデータ?ASCIIデータの句読文字のリストは、照合に依存するコードページに依存します。(この質問では、ASCIIデータを扱っています)。
  • 大文字と小文字を区別する検索または大文字と小文字を区別しない検索を扱っていますか?
  • 列にはどの照合順序が設定されていますか?照合は、コードページと大文字と小文字の区別の両方を教えてくれます。(この質問では私たちが扱っていますLatin1_General_CI_AS
  • ただ、標準の句読点文字を意味する用語「句読点」(例えばある.,;:、など)か、英数字以外の文字を意味するのでしょうか?
  • 空白文字は含まれていますか?
  • 制御文字は含まれていますか?
  • どのような通貨記号について¢£¥、など?
  • ©およびなどの記号はどうですか?
  • 「アルファ」と見なされる文字は何ですか?など、英語以外の文字があるÂÉÑßÞ付属?
  • この質問は英国のキーボードを扱っているため(この質問の説明を参照)、Æ/ æ文字はどうですか?

予想される動作をわかりやすくするために、次のクエリでは、Latin1文字セットのすべての256文字(つまりコードページ1252)と、@ Shaneisが提案するソリューションの2つのバリエーションがどのように動作するかを示します。最初のフィールド(ラベルはLatin1_General_CI_AS)はLIKE@Shaneisが提案した句(この記事の執筆時点Latin1_General_100_BIN2)を示し、2番目のフィールド(ラベルは)は、照合をオーバーライドしてバイナリ1を指定する変更を示します(つまり、末尾が_BIN2;の照合)。_BIN照合順序は廃止されているので、_BIN2バージョンにアクセスできる場合は使用しないでください。A-Z現在の照合順序では大文字と小文字が区別されないため、大文字を除外するために範囲を追加する必要もありました。

;WITH nums AS
(
  SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) AS [Decimal]
  FROM   [master].[sys].[all_objects]
)
SELECT nm.[Decimal],
       CHAR(nm.[Decimal]) AS [Character],
       CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9]%'
               THEN 'x' ELSE '' END AS [Latin1_General_CI_AS],
       CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9A-Z]%' COLLATE Latin1_General_100_BIN2
               THEN 'x' ELSE '' END AS [Latin1_General_100_BIN2]
FROM   nums nm;

更新

それは言及すべきことであるが、IF 1は、真に「句読点」(とない「通貨記号」、「数学記号」など)に分類されている文字を見つけるために求めている、とのIF 1は、カスタムのロード/ SQLCLRを使用してから禁止されていませんアセンブリ(SQLCLRはSQL Server 2005で導入されましたが、特にAzure SQL Database V12がアセンブリをサポートしているため、これを許可しない正当な理由はまだありませんSAFE)なら、正規表現を使用できますが、ほとんどの人はそうではありません。推測します。

正規表現を使用してより機能的な文字範囲を構築するのではなく、または\w(「単語」文字を意味する)などを使用するのではなく、フィルタリングする文字のUnicodeカテゴリを指定できます。定義済みのカテゴリがいくつかあります。 :

https://www.regular-expressions.info/unicode.html#category

「InBengali」、「InDingbats」、「InOptical_Character_Recognition」など、フィルタリングするUnicodeブロックを指定することもできます。

https://www.regular-expressions.info/unicode.html#block

SQL Server用のRegEx関数を作成する例は多数あります(ただし、ほとんどの例はSQLCLRのベストプラクティスに従っていません)。または、無料バージョンのSQL#ライブラリ(私が作成したもの)をダウンロードして、次のようにスカラーRegEx_IsMatch関数を使用できます。 :

SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)

この\p{P}表現は、\p= Unicodeカテゴリ、および{P}=すべての句読点を意味します(「コネクタの句読点」などの特定の種類の句読点とは対照的)。また、「句読点」カテゴリには、すべての言語にわたるすべての句読点が含まれています。Unicode.orgサイトの完全なリストは、次のリンクで確認できます(現在、そのカテゴリには717のコードポイントがあります)。

http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D

上記のテストクエリの更新されたバージョン(SQL#.RegEx_IsMatch\p{P}で使用する別のフィールドを含む)、およびコードページ1252のすべての256文字にわたるすべての3つのテストの結果(Latin1_General)が、PasteBin.comの次の場所に投稿されています。

文字のタイプをフィルタリングするためのT-SQLクエリと結果


更新
以下は関連する議論で言及されました:

アクセント記号付きの文字について良い点を説明しました。世界中のホテル名であり、名前にアクセント記号付きの文字が含まれています。私の問題では、これらを有効なアルファ文字として分類したいと思います。

この場合:

  1. Latin1文字セット/コードページに含まれる英語以外の11文字があり、a-z範囲と一致しません。彼らは以下の通りですð Ð Þ þ œ Œ š Š ž Ž Ÿ。これらはワイルドカードに追加する必要があり、現時点では必要ありませんA-Zが、パターンを大文字と小文字を区別する照合で正しく機能させるために追加しても問題ありません。最終結果は次のとおりです。
    LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'

  2. このデータには「世界中のホテル名」を含めることができるので、すべての言語のすべての文字を格納できるように列のデータ型を変更することを強くお勧めNVARCHARします。これをそのままにしVARCHARておくと、ラテン語ベースの言語しか表現できず、ラテン語関連の追加の文字を提供する6つの補足的なUnicodeカテゴリが指定された言語では完全に表現できないため、最終的にデータ損失のリスクが非常に高くなります。


5

私はこれを少し単純化しすぎているかもしれませんが、英数字の値が削除されたときに句読点だけが残っていると言うと、次は英数字以外の文字を含む文字列を検索します。

Create Table #Test
(
Value   VarChar(10)
) 
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')

-- Original
Select      *
From        #Test
Where       Value like '[0-9][0-9][0-9][a-z]'

-- Non Alpha-numeric
SELECT * FROM #Test WHERE Value LIKE '%[^a-z0-9]%';

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