TOPサーバ構築・運用> 実験3:文字の長さを正しく計測できるかやってみる
Vista&データベース
Windows Vistaで発生するデータベーストラブル対応指南

第3回:Microsoft SQL Server 2005で必要な対処(後編)

著者:一志 達也   2007/7/20
前のページ  1  2  3  次のページ
実験3:文字の長さを正しく計測できるかやってみる

   アプリケーションの種類にもよるが、文字列の長さを関数で測定して、何かしらの処理を行うという場面がある。サロゲートペアは2文字分の領域を使って1文字を表現するから、果たして文字列の長さを測定するとどうなるのかは気になるところだ。

   では下記のSQLを実行してみよう。
select ncharcol, len(ncharcol), datalength(ncharcol) from unicode_test;

   するとこのような結果が得られた。


(画像をクリックすると別ウィンドウに拡大図を表示します)

   このように、サロゲートペアを使った文字列の長さは、8バイト4文字分として計測される。実際には2文字なのだから処理に狂いが生じてしまうだろう。


実験4:文字を正しく切り出せるかやってみる

   これまでの実験で行った処理と同じようにように、文字列の処理として文字の一部を切り出す場面もアプリケーションではよくあるものだ。ここではsubstring関数を使って先頭の1文字を切り出す処理を、これまでの実験と同様の条件で実験してみるとしよう。

   まずSQLを実行する。

select substring(ncharcol, 1, 1) from unicode_test;

   するとこのような結果が得られた。


(画像をクリックすると別ウィンドウに拡大図を表示します)

   この結果を見ると正しく切り出せていないのだが、これはサロゲートペアの先頭2バイトだけを切り出してしまうために起こるものだ。実際には4バイトで1文字なので、結果として文字を正しく戻せないわけである。


回避策はあるのか

   これまでの実験から明らかになったように、表のデータ型を変更し、文字列を扱う箇所のすべてに「Nプレフィックス」を付け加えたとしても問題が残る。これらを回避する手段は、ほんの少し前まで存在しなかったのだが、つい最近になって対処が明確になってきた。それをいくつか紹介しよう。


照合順序の設定

   検索処理の条件をうまく処理できない問題については、SQL Serverの照合順序をJapanese_90_BIN2などにすれば対応できる。たとえば先の実験2で正しく動作しなかったSQLも、下記のようにすれば正しい結果を得られる。

select * from unicode_test where ncharcol like N'??%' COLLATE Japanese_90_BIN2;

   しかし、すべてのSQLに照合順序を指定するなど、アプリケーション側の対応として現実解とは思えない。そこでデータベースのプロパティを編集して、これに対処することになるだろう。幸いなことにSQL Server Management Studioを使えば、データベースとしての規定の照合順序を変更できる。

   実際、筆者も変更してみたところ、SQLに照合順序を指定しなくても検索処理を正しく行うようになった。

照合順序の変更
図1:照合順序の変更
(画像をクリックすると別ウィンドウに拡大図を表示します)

   ただしこの解決策にも問題点があり、TempDBやMasterなどのシステムデータベースには変更を反映できない。これらの照合順序はインスタンスを作成する時点で指定したものから変更できないようになっているためだ。

   アプリケーションの作り方にも依存するが、処理の途中経過の記録にTempDBを用いるという手法は、SQL Serverユーザの間では行われていると思う。こうした場合には、照合順序の問題を引き起こす可能性があるから、やはりインスタンス全体を再作成するしかないだろう。すなわち、SQL Server自体の再インストールを行う、ということだ。

前のページ  1  2  3  次のページ


一志 達也
著者プロフィール
一志 達也
SI企業において、アプリケーション開発や、データベースを中心としたインフラを担当。開発者向け、初心者向けの講座を得意とする。著書に「やさしいOracle PL/SQL入門」「Oracle10g 真剣勝負」などがある。


INDEX
第3回:Microsoft SQL Server 2005で必要な対処(後編)
  実験2:曖昧検索を正しくできるかやってみる
実験3:文字の長さを正しく計測できるかやってみる
  文字関数をCLRで作成