日本語照合順序 Japanese と Japanese_XJIS_100、Japanese_Bushu_Kakusu_100 の比較


はじめまして、マイクロソフト保瀬です。SQL Server 開発部門でテスターをしております。日本のSQL Serverチームがブログを開設してから1年以上が経ちますが、遅れ馳せながら今回はじめて書きます。これを機にできる限り、継続的かつ頻繁に情報発信できればと思います。よろしくお願いします。


初回は、トピックとしてあまり取り上げられないSQLの照合順序についていろいろと見ていこうと思います。CTP版やRC版等をお試しになっている方はお気づきと思いますが、新たに2つ照合順序が追加されています。


SQL Server に新規に照合順序が追加されることなった背景に Windows Server 2008 と足並みをそろえるという目的がありました。Windows Vistaを既にご使用の方は、お気付きと思いますが、コントロール パネルの「地域と言語のオプション」のところで並べ替えの設定ができます(下図参照)。ここで「XJIS」または「部首/画数」の何れかを指定できるようになっています。今回 SQL Server に新たに追加された日本語の照合順序名である Japanese_XJIS_100 及び Japanese_Bushu_Kakusu_100 Windows Vista Windows Server 2008 で指定可能となった「並べ替え」の内容に沿うような形で追加されています。



地域と言語のオプション 


Japanese_XJIS_100 の照合順序で何が変わったか、特に以前からあるJapanese 照合順序などと比較した場合の文字の並び替えなど動作について見ていきましょう。まずは「論より証拠」で、実際にそれぞれJapanese_XJIS_100Japaneseの照合順序でソートした場合の結果を比べていくことにします。尚、今回は一文字単位の比較としました。例えば、「は」と「ば」を比較するのであれば where 句の内容として "where N'' < N'' collate Japanese_XJIS_100_CI_AS" といった具合で比較していくことにしました。2文字以上の文字列を含む比較となると、内部エンジンの文字列ソートについて触れておく必要が出てくるので、それはまた別の機会にしておきます。


比較内容として、今回は平仮名・片仮名の文字(単一文字のみ)を使って比較してみました。全ての五十音文字を使用するとかなりのテストパターンになるので、今回は清音、濁音、半濁音、平仮名、片仮名等の観点から、Japanese Japanese_XJIS_100Japanese_Bushu_Kakusu_100 の各照合順序の比較結果の違い検証してみました。


下記表1にグループ分けされた五十音文字を示します:


表1(参考:JIS X 4061「日本語文字列照合順番」)


























































































    グループ


    グループ文字


    清音


    大文字(L)・小文字(S)


    平仮名 (H)/


    片仮名 (K)


    1


    あいうえおかきくけこさしすせとたちつてと


    なにぬねのはひふへほまみむめもやゆよ


    らりるれろわゐゑをん


    清音


    L


    H


    2


    がぎぐげござじずぜぞだぢづでどばびぶべぼ


    濁音


    L


    H


    3


    ぱぴぷぺぽ


    半濁音


    L


    H


    4


    ぁぃぅぇぉっゃゅょゎ


    清音


    S


    H


    (※)5



    清音


    (繰り返し文字)


    H


    (※)6



    濁音


    (繰り返し文字)


    H


    7


    アイウエオカキクケコサシスセソタチツテト


    ナニヌネノハヒフヘホマミムメモヤユヨ


    ラリルレロワヰヱヲン


    清音


    L


    K


    8


    ヴガギグゲゴザジズゼゾダヂヅデドバビブベボ


    濁音


    L


    K


    9


    パピプペポ


    半濁音


    L


    K


    10


    ァィゥェォヵヶッャュョヮ


    清音


    S


    K


    (※)11



    清音


    (繰り返し文字)


    K


    (※)12



    濁音


    (繰り返し文字)


    K


    (※)13



    清音


    (長音)


    K


     


    (※)今回の検証では 繰り返し文字 を使用してのテストは除きました


     


比較方法の基本的な考え方は、上記表1のグループ間での比較を行います。たとえば、grp1 (グループ1)と grp2 (グループ2)を比較する場合、まず grp1の代表文字として「つ」、grp2 の代用文字として「づ」を対象となる比較文字として、さまざまな照合順序を使って比較します。T-SQL文的に記述すると、こんな感じです:



     


    declare @ch1 nchar, @ch2 nchar


    set @ch1 = N'つ'


    set @ch2 = N'づ'


    select case


    when @ch1 = @ch2 collate Japanese_ci_as then 0


    when @ch1 < @ch2 collate Japanese_ci_as then -1


    else 1


    end


     


尚、今回の検証ではグループ間内での比較は行っていません。例えば、grp1 にある「あ」と「い」との比較、grp2 にある「が」と「ぎ」の比較など。



     


各グループの代表文字は以下の内容で検証しました:




















































































































    test ID


    ch1


    ch2


    グループ間比較内容


    1




    grp1 vs grp2


    2




    grp1 vs grp3


    3




    grp1 vs grp4


    4




    grp1 vs grp7


    5




    grp1 vs grp8


    6




    grp1 vs grp9


    7




    grp1 vs grp10


    8




    grp2 vs grp3


    9




    grp2 vs grp4


    10




    grp2 vs grp7


    11




    grp2 vs grp8


    12




    grp2 vs grp9


    13




    grp2 vs grp10


    14




    grp3 vs grp7


    15




    grp3 vs grp9


    16




    grp4 vs grp7


    17




    grp4 vs grp10


    18




    grp7 vs grp8


    19




    grp7 vs grp10


    20




    grp8 vs grp9


    21




    grp8 vs grp10


     


さらに、検証で使用した照合順序名は、Japanese_xx_xxJapanese_XJIS_100_xx_xx Japanese_Bushu_Kakusu_100_xx_xx です。"xx_xx" の部分はいわゆる Windows 照合順序サフックス」の部分で 18 通りありますが、今回は BIN系を除く16 通りのものを対象としました。ちなみに、こちらのT-SQL文でサフックスの内容を確認できます:



     


    select name from fn_helpcollations() where name like 'Japanese_XJIS_100%'


    go


     


実際のテストでは、テスト結果を格納するためのテーブルにテスト パターンを挿入しておき、直接テーブルに結果を更新するようにテストしました。テスト 結果の(一部抜粋)内容は下記の内容となりました


 























































    id


    ch1


    ch2


    Collation


    CompareResult


    Notes


    1




    Japanese_CI_AI


    0


    grp1 vs grp2


    2




    Japanese_CI_AI


    0


    grp1 vs grp3


    3




    Japanese_CI_AI


    0


    grp1 vs grp4


    4




    Japanese_CI_AI


    0


    grp1 vs grp7


    5




    Japanese_CI_AI


    0


    grp1 vs grp8


    6




    Japanese_CI_AI


    0


    grp1 vs grp9


     


結果テーブルの主な列の内容は






















    内容


    ch1, ch2


    比較対象文字


    Collation


    比較時に使用した照合順序名


    CompareResult


    結果比較(0, -1, 1)の何れか


    0:'' = ''


    -1'' < ''


    1'' > ''


    Notes


    比較対照グループ


     


     


以下に検証結果をまとめてみました:


(後述補足説明を参照)



     














































































































    グループ間比較


    照合順序名


    Japanese_xx_xx


    照合順序名


    Japanese_XJIS_100_xx_xx


    照合順序名


    Japanese_Bushu_Kakusu_100_xx_xx


    grp1 vs grp2



    1. Windows照合順序サフィックス(以下 CompStyle) AI が指定されている場合、grp1 = grp2 となった

    2. CompStyle AS」が指定されている場合、grp1 < grp2 となった

    常に grp1 < grp2 となった


    同左


    grp1 vs grp3



    1. CompStyle に「AI」が指定されている場合、grp1 = grp3 となった

    2. CompStyle に「AS」が指定されている場合、grp1 < grp3 となった

    常にgrp1 < grp2 となった


    同左


    grp1 vs grp4



    1. CompStyle に「AI」が指定されている場合、grp1 = grp4 となった

    2. CompStyle に「AS」が指定されている場合、grp1 > grp4 となった

    常に grp1 > grp4 となった


    同左


    grp1 vs grp7



    1. CompStyleに「KS」げ指定されていない 場合

    2. grp1 = grp7 となった


    3. CompStyle に「KS」が指定されている場合に、grp1 > grp7 となった

    同左


    同左


    grp1 vs grp8



    1. CompStyle に「AI_KS」が指定されている場合に、grp1 > grp8 となった

    2. CompStyle に「AS」が指定されている場合に grp1 < grp8 となった

    3. 上記以外は grp1 = grp8 となった

    常に grp1 < grp8 となった


    同左


    grp1 vs grp9



    1. CompStyle に「AI_KS」が指定されている場合に、grp1 > grp9 となった

    2. CompStyle に「AS」が指定されている場合に、grp1 < grp9 となった

    3. 上記以外は grp1 = grp9 となった

    常に grp1 < grp9 となった


    同左


    grp2 vs grp3



    1. CompStyle に「AI」が指定されている場合に、grp2 = grp3 となった

    2. CompStyle に「AS] が指定されている場合に、grp2 < grp3 となった

    常に grp2 < grp3 となった


    同左


    grp2 vs grp4



    1. CompStyle に「AI」が指定されている場合、grp2 = grp4 となった

    2. CompStyle に「AS」が指定されている場合、grp2 > grp4 となった

    常に grp2 > grp4 となった


    同左


    grp2 vs grp7



    1. CompStyle grp2 = grp7 when CI_AI or CI_AI_WS

    2. grp2 > grp7 for other


    常にgrp2 > grp7 となった


    同左


    grp2 vs grp8



    1. CompStyle に「KS」が指定されていない 場合に grp2 = grp8 となった

    2. CompStyle に「KS」が指定されている場合に、grp2 > grp8 となった

    同左


    同左


    grp2 vs grp9



    1. CompStyle に「KS」が指定されていない場合に grp2 = grp8 となった

    2. CompStyle に「KS」が指定されている場合に、grp2 > grp8 となった

    同左


    同左


    grp2 vs grp10



    1. CompStyle に「AI」が指定されている場合に、grp2 = grp10 となった

    2. CompStyle に「AS」が指定されている場合に、grp2 > grp10 となった

    常に grp2 > grp10 となった


    同左


    grp3 vs grp7



    1. CompStyle に「KS」が指定されていない場合に grp3 = grp7 となった

    2. CompStyle に「KS」が指定されている場合に、gr32 > grp7 となった

    常に grp3 > grp7 となった


    同左


    grp3 vs grp9



    1. CompStyle に「KS」が指定されていない場合に、grp3 = grp9 となった

    2. CompStyle に「KS」が指定されている場合に、grp3 > grp9 となった

    同左


    同左


    grp4 vs grp10



    1. CompStyle に「KS」が指定されていない場合に、grp4 = grp10 となった

    2. CompStyle に「KS」が指定されている場合に、grp4 > grp10 となった

    同左


    同左


    grp4 vs grp7



    1. CompStyle に「AS」が指定されているば場合に、grp4 < grp7 となった

    2. CompStyle に「AI」が指定され且つ「KS」が指定されていない場合に、grp4 > grp7 となった

    3. 上記以外の場合は、grp4 = grp7 となった

    常に grp4 < grp7 となった


    同左


    grp7 vs grp8



    1. CompStyle に「AI」が指定されている場合に、grp7 = grp8 となった

    2. CompStyle に「AS」が指定されている場合に、grp7 < grp8 となった

    常に grp7 < grp8 となった


    同左


    grp7 vs grp10



    1. CompStyle に「AI」が指定されている場合に、grp7 = grp10 となった

    2. CompStyle に「AS」が指定されている場合に、grp7 > grp10 となった

    常に grp7 > grp10 となった


    同左


    grp8 vs grp9



    1. CompStyle に「AI」が指定されている場合に、grp8 = grp9 となった

    2. CompStyle に「AS」が指定されている場合に、grp8 < grp9 となった

    常にgrp8 < grp9 となった


    同左


    grp8 vs grp10



    1. CompStyle に「AI」が指定されている場合に、grp8 = grp10 となった

    2. CompStyle に「AS」が指定されている場合に、grp8 > grp10 となった

    常に grp8 > grp10 となった


    同左


     


    補足説明


  1. 上記表の4列目の「Japanese_Bushu_Kakusu_100_xxx」の結果は結局のところ Japanese_XJIS_100 と同様の結果となった。

  2.  


  3. たとえば、「grp1 vs grp2 」のテスト結果では、以下の照合順序名においては、「つ」=「づ」と比較される

  4. Japanese_CI_AI


    Japanese_CI_AI_WS


    Japanese_CI_AI_KS


    Japanese_CI_AI_KS_WS


    Japanese_CS_AI


    Japanese_CS_AI_WS


    Japanese_CS_AI_KS


    Japanese_CS_AI_KS_WS


     


    また、同様に以下の照合順序名では「つ」<「づ」と比較される


    Japanese_CI_AS


    Japanese_CI_AS_WS


    Japanese_CI_AS_KS


    Japanese_CI_AS_KS_WS


    Japanese_CS_AS


    Japanese_CS_AS_WS


    Japanese_CS_AS_KS


    Japanese_CS_AS_KS_WS


     


    そして、更に以下の新規照合順序名では、常に「つ」<「づ」と比較される


    Japanese_Bushu_Kakusu_100_CI_AI


    Japanese_Bushu_Kakusu_100_CI_AI_WS


    Japanese_Bushu_Kakusu_100_CI_AI_KS


    Japanese_Bushu_Kakusu_100_CI_AI_KS_WS


    Japanese_Bushu_Kakusu_100_CI_AS


    Japanese_Bushu_Kakusu_100_CI_AS_WS


    Japanese_Bushu_Kakusu_100_CI_AS_KS


    Japanese_Bushu_Kakusu_100_CI_AS_KS_WS


    Japanese_Bushu_Kakusu_100_CS_AI


    Japanese_Bushu_Kakusu_100_CS_AI_WS


    Japanese_Bushu_Kakusu_100_CS_AI_KS


    Japanese_Bushu_Kakusu_100_CS_AI_KS_WS


    Japanese_Bushu_Kakusu_100_CS_AS


    Japanese_Bushu_Kakusu_100_CS_AS_WS


    Japanese_Bushu_Kakusu_100_CS_AS_KS


    Japanese_Bushu_Kakusu_100_CS_AS_KS_WS


    Japanese_XJIS_100_CI_AI


    Japanese_XJIS_100_CI_AI_WS


    Japanese_XJIS_100_CI_AI_KS


    Japanese_XJIS_100_CI_AI_KS_WS


    Japanese_XJIS_100_CI_AS


    Japanese_XJIS_100_CI_AS_WS


    Japanese_XJIS_100_CI_AS_KS


    Japanese_XJIS_100_CI_AS_KS_WS


    Japanese_XJIS_100_CS_AI


    Japanese_XJIS_100_CS_AI_WS


    Japanese_XJIS_100_CS_AI_KS


    Japanese_XJIS_100_CS_AI_KS_WS


    Japanese_XJIS_100_CS_AS


    Japanese_XJIS_100_CS_AS_WS


    Japanese_XJIS_100_CS_AS_KS


    Japanese_XJIS_100_CS_AS_KS_WS


     


  5. このほかに、「grp1 vs grp7」(表中の5行目の結果)の結果について見ますと、以下の照合順序名で、「つ」=「ツ」と比較される

  6. Japanese_CI_AI


    Japanese_CI_AI_WS


    Japanese_CI_AS


    Japanese_CI_AS_WS


    Japanese_CS_AI


    Japanese_CS_AI_WS


    Japanese_CS_AS


    Japanese_CS_AS_WS


    Japanese_Bushu_Kakusu_100_CI_AI


    Japanese_Bushu_Kakusu_100_CI_AI_WS


    Japanese_Bushu_Kakusu_100_CI_AS


    Japanese_Bushu_Kakusu_100_CI_AS_WS


    Japanese_Bushu_Kakusu_100_CS_AI


    Japanese_Bushu_Kakusu_100_CS_AI_WS


    Japanese_Bushu_Kakusu_100_CS_AS


    Japanese_Bushu_Kakusu_100_CS_AS_WS


    Japanese_XJIS_100_CI_AI


    Japanese_XJIS_100_CI_AI_WS


    Japanese_XJIS_100_CI_AS


    Japanese_XJIS_100_CI_AS_WS


    Japanese_XJIS_100_CS_AI


    Japanese_XJIS_100_CS_AI_WS


    Japanese_XJIS_100_CS_AS


    Japanese_XJIS_100_CS_AS_WS


     


    そして、更に以下の照合順序名で、「つ」>「ツ」と比較される


    Japanese_CI_AI_KS


    Japanese_CI_AI_KS_WS


    Japanese_CI_AS_KS


    Japanese_CI_AS_KS_WS


    Japanese_CS_AI_KS


    Japanese_CS_AI_KS_WS


    Japanese_CS_AS_KS


    Japanese_CS_AS_KS_WS


    Japanese_Bushu_Kakusu_100_CI_AI_KS


    Japanese_Bushu_Kakusu_100_CI_AI_KS_WS


    Japanese_Bushu_Kakusu_100_CI_AS_KS


    Japanese_Bushu_Kakusu_100_CI_AS_KS_WS


    Japanese_Bushu_Kakusu_100_CS_AI_KS


    Japanese_Bushu_Kakusu_100_CS_AI_KS_WS


    Japanese_Bushu_Kakusu_100_CS_AS_KS


    Japanese_Bushu_Kakusu_100_CS_AS_KS_WS


    Japanese_XJIS_100_CI_AI_KS


    Japanese_XJIS_100_CI_AI_KS_WS


    Japanese_XJIS_100_CI_AS_KS


    Japanese_XJIS_100_CI_AS_KS_WS


    Japanese_XJIS_100_CS_AI_KS


    Japanese_XJIS_100_CS_AI_KS_WS


    Japanese_XJIS_100_CS_AS_KS


    Japanese_XJIS_100_CS_AS_KS_WS


     


     


     


さあ、結果としていかがでしたでしょうか?日本語の観点からこの結果が正しいか否かは、読者の主観にお任せします。



     


今回の検証で使用したビルドは RC0 相当のものでしたが、おそらくリリース時でも同様な動作になるものと思われます。


では、次回はJapanese_Bushu_Kakusu_100 ついて、いろいろと探っていこうと思います。



     


     


     


ご参考までに、今回の検証で使用したスクリプトを載せておきます。


興味のある方、今回使用した「代表文字」以外の文字で是非試してみてください。


/*****************************************************/


set nocount on


go


if object_id('compChar') is not null


drop table compChar


go


create table compChar(id int identity, ch1 nchar(1), ch2 nchar(2), notes varchar(100))


go


insert compChar values(N'つ', N'づ', 'grp1 vs grp2')


insert compChar values(N'は', N'ぱ', 'grp1 vs grp3')


insert compChar values(N'つ', N'っ', 'grp1 vs grp4')


insert compChar values(N'つ', N'ツ', 'grp1 vs grp7')


insert compChar values(N'つ', N'ヅ', 'grp1 vs grp8')


insert compChar values(N'は', N'パ', 'grp1 vs grp9')


insert compChar values(N'つ', N'ッ', 'grp1 vs grp10')


insert compChar values(N'ば', N'ぱ', 'grp2 vs grp3')


insert compChar values(N'づ', N'っ', 'grp2 vs grp4')


insert compChar values(N'づ', N'ツ', 'grp2 vs grp7')


insert compChar values(N'づ', N'ヅ', 'grp2 vs grp8')


insert compChar values(N'ば', N'バ', 'grp2 vs grp9')


insert compChar values(N'づ', N'っ', 'grp2 vs grp10')


insert compChar values(N'ぱ', N'ハ', 'grp3 vs grp7')


insert compChar values(N'ぱ', N'パ', 'grp3 vs grp9')


insert compChar values(N'っ', N'ツ', 'grp4 vs grp7')


insert compChar values(N'っ', N'ッ', 'grp4 vs grp10')


insert compChar values(N'ツ', N'ヅ', 'grp7 vs grp8')


insert compChar values(N'ツ', N'ッ', 'grp7 vs grp10')


insert compChar values(N'バ', N'パ', 'grp8 vs grp9')


insert compChar values(N'ヅ', N'ッ', 'grp8 vs grp10')


go


if object_id('TestResult') is not null


drop table TestResult


go


create table TestResult (


id int identity,


ch1 nchar(1),


ch2 nchar(2),


Collation nvarchar(128),


CompareResult int,


Notes varchar(100))


go


insert TestResult


select ch1, ch2, name, -2, Notes


from compChar t, fn_helpcollations() c


where COLLATIONPROPERTY(name, 'version') <> 1 and name not like 'Japanese_Unicode%' and


name like 'japan%' and name not like '%bin%'


go


 


declare cur cursor for select id, ch1, ch2, Collation from TestResult


declare @id int, @ch1 nchar(1), @ch2 nchar(1), @colName nvarchar(128)


declare @cmd nvarchar(1000)


open cur


fetch cur into @id, @ch1, @ch2, @colName


while @@fetch_status = 0


begin


set @cmd = 'update TestResult set CompareResult = case


when N''' + @ch1 + ''' = N''' + @ch2 + ''' collate ' + @colName + ' then 0


when N''' + @ch1 + ''' < N''' + @ch2 + ''' collate ' + @colName + ' then -1


else 1


end where id = ' + convert(varchar(4), @id)


exec(@cmd)


fetch cur into @id, @ch1, @ch2, @colName


end


close cur


deallocate cur


 


select * from TestResult



     

Comments (2)

  1. 日本語照合順序 Japanese と Japanese_XJIS_100、Japanese_Bushu_Kakusu_100 の比較を行っているページ

  2. わんくまでもポストしましたが、こちらでも。 SQL server開発チームのブログにて、SQL Server 2008より増える照合順序の比較を行った記事がありました。 日本語照合順序 Japanese

Skip to main content