2

URL を列に格納したい。RFC 3986によると、US-ASCII は URL を構成する文字セットです。

SQL Server には、US-ASCII 文字セットのすべての文字をエンコードできる VARCHAR 型と、コード ページに依存する 128 個の文字があります。

CHECK 制約を使用して、列の値に US-ASCII 文字セットの印刷可能な文字のみが含まれるようにしたいと考えています。つまり、ASCII(@char) >= 32 AND ASCII(@char) < 127文字列内のすべての文字に対して。

LIKE 式を使用してチェック制約でこれを行うことができると思いますが、適切なパターンが見つかりません。Itzik Ben-Gan の許容範囲外の任意の文字に一致するトリックを適応させようとしています。これは彼の記事Can I convert this string to an integer?で提示されています。.

テスト ハーネスでは@TestData、列に挿入する候補のテーブル@Patterns、LIKE 演算子で使用するパターンのテーブルを作成し、各パターンを各候補と照合した結果を選択します。

DECLARE @TestData TABLE (
  String VARCHAR(60) COLLATE Latin1_General_CI_AS NOT NULL
);

INSERT INTO @TestData(String)
VALUES
  ('€ÿ'),
  ('ab3'),
  ('http://www.google.com/'),
  ('http://www.example.com/düsseldorf?neighbourhood=Lörick'),
  ('1234');

DECLARE @Patterns TABLE (
  Pattern VARCHAR(12) COLLATE Latin1_General_CI_AS NOT NULL
);

INSERT INTO @Patterns (Pattern)
VALUES
  ('%[^0-9]%'),
  ('%[^' + CHAR(32) + '-' + CHAR(126) + ']%');

SELECT
  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ID,
  String,
  Pattern,
  CASE WHEN String NOT LIKE Pattern THEN 1 ELSE 0 END AS [Match]
FROM @TestData CROSS JOIN @Patterns;

に挿入される最初の行@Patternsは、Itzik が数字以外の文字を照合するために使用するパターンに似ています。2 行目は、印刷可能な US-ASCII 文字の範囲外の文字にこれを適応させようとする私の試みです。

上記のバッチを実行すると、次の結果セットが返されます。

ID   String                                                   Pattern      Match
---  -------------------------------------------------------- ------------ ------
 1    €ÿ                                                       %[^0-9]%     0
 2    ab3                                                      %[^0-9]%     0
 3    http://www.google.com/                                   %[^0-9]%     0
 4    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^0-9]%     0
 5    1234                                                     %[^0-9]%     1
 6    €ÿ                                                       %[^ -~]%     0
 7    ab3                                                      %[^ -~]%     0
 8    http://www.google.com/                                   %[^ -~]%     0
 9    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^ -~]%     0
 10   1234                                                     %[^ -~]%     0

予想どおり、候補に数字のみが含まれているため、行 5 は一致します。行 1 ~ 4 の候補は数字だけではないため、パターンに一致しません。

予想どおり、行 6 の候補はパターンに一致しません。これは、「high ASCII」文字が含まれているためです。

行 7、8、および 10 の候補は、印刷可能な US-ASCII 文字しか含まれていないため、一致すると予想されます。しかし、これらは一致しません。

LIKE 式のパターンの何が問題になっていますか?

4

1 に答える 1

3

質問のコメントと同様の質問への回答で示唆されているように、バイナリ照合句を使用する必要があります。

select ステートメントを次のように変更すると、次のようになります。

SELECT
  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ID,
  String,
  Pattern,
  CASE WHEN String NOT LIKE Pattern COLLATE Latin1_General_BIN THEN 1 ELSE 0 END AS [Match]
FROM @TestData CROSS JOIN @Patterns;

次の結果セットが得られます。

ID   String                                                   Pattern      Match
---  -------------------------------------------------------- ------------ ------
 1    €ÿ                                                       %[^0-9]%     0
 2    ab3                                                      %[^0-9]%     0
 3    http://www.google.com/                                   %[^0-9]%     0
 4    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^0-9]%     0
 5    1234                                                     %[^0-9]%     1
 6    €ÿ                                                       %[^ -~]%     0
 7    ab3                                                      %[^ -~]%     1
 8    http://www.google.com/                                   %[^ -~]%     1
 9    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^ -~]%     0
 10   1234                                                     %[^ -~]%     1

これで、Match 列に期待値が含まれるようになりました。

于 2012-05-25T11:18:10.317 に答える