2017-10-05 9 views
0

問題

私は、SQL Server 2008 R2上で次のクエリを実行すると、二つの異なる日本のUnicode文字列が等しいものとして扱われます。私は漢字以下カナは、半値幅があることを知っているSQL Server 2008 R2日本語(NVARCHAR)文字列の比較でエラーが発生しましたか?

SELECT 
    CASE 
     WHEN N'食料' = N'食料ㇰ ㇱ ㇲ ㇳ' 
      THEN 1 
     ELSE 0 
    END; 

--result: 1 

が、似たような全角かながないので、私は幅の感度やカナの感度を問題には期待しません。カナは全角のバージョンに置き換えている場合は、比較が期待通りに動作します。

SELECT 
    CASE 
     WHEN N'食料' = N'食料ク シ ス ト' 
      THEN 1 
     ELSE 0 
    END; 

--result: 0 

未遂ソリューション

これは、問題はSQL_Latin1_General_CP1_CI_ASである私の照合に関連しているかもしれないと思うように私を導きました。

最初に、私はLatin1_General_CI_ASを試しましたが、それはSQL Unicode比較の奇妙な点でありましたが、それで問題は解決しませんでした。

次に、最も制限の少ない照合(すべての感度)を使用すると考えましたが、Latin1_General_CS_AS_KS_WSJapanese_Unicode_CS_AS_KS_WSを含む他の照合は、半角の後尾かなを使用したときの結果を変更しませんでした後ろかな)。文字列はバイトレベルで異なっていることを確認し

、私は文字列に対してN(NVARCHAR)の指定を除去した後、半値幅末尾仮名でクエリを実行し、それが0の期待される結果を返す検証しました。

質問

ここでは何が起こっていますか?私は単に正しい照合を試みていませんか?これはSQL Server 2008 R2のエラーですか?私が気付いていない日本語のUnicodeに特有のものがありますか?なぜ、半角の後ろかなの存在がこれらの文字列を異なるものにしないのでしょうか?

PS私は日本語を知らないので、私がキャラクターの記述を乱すと、私は謝ります。

答えて

1

大量の照合では、最初の例の文字が1つの空白に等しくなります。

文字列の比較を行うとき、SQLサーバーは文字列の末尾に末尾の空白を取り除きます(ただし、LIKEを使用する場合は例外ですが、ここでは実行していません)。

たとえば、文字列N'食料ㇰ ㇱ ㇲ ㇳ'では、の後のすべての文字が後続の空白として扱われ、文字列比較の際に削除されます。

が与えられた照合でクイックチェックを行うには、次のクエリを実行できます。

WITH 
    Vals AS (SELECT FullString, StringNum FROM (VALUES (N'食料', 1), (N'食料ㇰ ㇱ ㇲ ㇳ', 2), (N'食料ク シ ス ト', 3)) AS T(FullString, StringNum)), 
    CTE AS -- A recursive CTE to split the characters up in your strings and check the individual characters. 
    (
     SELECT FullString, 
       StringNum, 
       IndividualCharacter = SUBSTRING(FullString, 1, 1), 
       UnicodeNumber = UNICODE(SUBSTRING(FullString, 1, 1)), 
       UnicodeBinary = CAST(SUBSTRING(FullString, 1, 1) AS VARBINARY(2)), 
       CharPosition = 1 
     FROM Vals 
     UNION ALL 
     SELECT V.FullString, 
       V.StringNum, 
       IndividualCharacter = SUBSTRING(V.FullString, C.CharPosition + 1, 1), 
       UnicodeNumber = UNICODE(SUBSTRING(V.FullString, C.CharPosition + 1, 1)), 
       UnicodeBinary = CAST(SUBSTRING(V.FullString, C.CharPosition + 1, 1) AS VARBINARY(2)), 
       CharPosition = C.CharPosition + 1 
     FROM Vals AS V 
     JOIN CTE AS C 
      ON C.StringNum = V.StringNum 
     WHERE C.CharPosition + 1 <= LEN(V.FullString) 
    ) 
SELECT C.*, 
     CharacterEqualToSpace = CASE WHEN NCHAR(C.UnicodeNumber) COLLATE Japanese_Unicode_CS_AS_KS_WS = NCHAR(32) THEN 1 ELSE 0 END, 
     FullStringWithoutSpace = SUBSTRING(C.FullString, 1, (SELECT MAX(CharPosition) FROM CTE AS C2 WHERE C2.StringNum = C.StringNum AND NCHAR(C2.UnicodeNumber) COLLATE Japanese_Unicode_CS_AS_KS_WS != NCHAR(32))) -- Eliminate white space on the end for this collation, with a substring ending at the last character that does not equal white space. 
FROM CTE AS C 
ORDER BY StringNum, CharPosition; 

をいくつかの簡単なテストを行ってから...どれBIN照合、Japanese_Bushu_Kakusu、Japanese_XJIS - スペースとして、これらの特定の文字を扱います日本の照合順序: - スペースとして、これらの特定の文字を扱いません。日本の照合順序日本人、Japanese90、Japanese_Unicode

注意:空白として扱われるJapanese_Unicode_CS_AS_KS_WSには21000文字以上あります。これは、特定の照合に対して次のようなクエリを実行することで確認できます。

WITH T(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)), -- 16 
    T2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM T AS A CROSS JOIN T AS B CROSS JOIN T AS C CROSS JOIN T) -- 16^4. 
SELECT WhiteSpaceCharacters = NCHAR(N) 
FROM T2 
WHERE NCHAR(N) COLLATE Japanese_Unicode_CS_AS_KS_WS = NCHAR(32); 
関連する問題