plpgsql 全角カナ 半角カナ 比較
2007/09/27
postgresqlでsqlのユーザ関数を定義できることは知っていましたが、手を出したことはありませんでした。
http://www.postgresql.jp/document/pg721doc/programmer/plpgsql.html
半角カナと全角カナを区別せずに検索するという仕様があるとします。アプリ(javaとかphpとか)でDBからデータを全部取ってきてから判定するのはいろんな意味で無駄が多くなります。
postgresqlのsql関数を試すチャンスと思い試してみたのが以下です。
-- # 引数の文字列の半角カナを全角カナに変換する関数 -- drop function kana2full(varchar); create function kana2full(varchar) returns varchar as ' declare p1 alias for $1; str varchar; len int; i int; zenkakus varchar; hankakus varchar; begin str := p1; str := replace(str, ''ガ'', ''ガ''); str := replace(str, ''ギ'', ''ギ''); str := replace(str, ''グ'', ''グ''); str := replace(str, ''ゲ'', ''ゲ''); str := replace(str, ''ゴ'', ''ゴ''); str := replace(str, ''ザ'', ''ザ''); str := replace(str, ''ジ'', ''ジ''); str := replace(str, ''ズ'', ''ズ''); str := replace(str, ''ゼ'', ''ゼ''); str := replace(str, ''ゾ'', ''ゾ''); str := replace(str, ''ダ'', ''ダ''); str := replace(str, ''ヂ'', ''ヂ''); str := replace(str, ''ヅ'', ''ヅ''); str := replace(str, ''デ'', ''デ''); str := replace(str, ''ド'', ''ド''); str := replace(str, ''バ'', ''バ''); str := replace(str, ''ビ'', ''ビ''); str := replace(str, ''ブ'', ''ブ''); str := replace(str, ''ベ'', ''ベ''); str := replace(str, ''ボ'', ''ボ''); str := replace(str, ''パ'', ''パ''); str := replace(str, ''ピ'', ''ピ''); str := replace(str, ''プ'', ''プ''); str := replace(str, ''ペ'', ''ペ''); str := replace(str, ''ポ'', ''ポ''); str := replace(str, ''ヴ'', ''ヴ''); zenkakus := ''アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ''; hankakus := ''アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ''; len := length(zenkakus); for i in 0 .. len loop str := replace(str, substr(hankakus, i, 1), substr(zenkakus, i, 1)); end loop; return str; end; ' language 'plpgsql' ; -- # 引数の文字列の全角カナを半角カナに変換する関数 -- drop function kana2half(varchar); create function kana2half(varchar) returns varchar as ' declare p1 alias for $1; str varchar; len int; i int; zenkakus varchar; hankakus varchar; begin str := p1; str := replace(str, ''ガ'', ''ガ''); str := replace(str, ''ギ'', ''ギ''); str := replace(str, ''グ'', ''グ''); str := replace(str, ''ゲ'', ''ゲ''); str := replace(str, ''ゴ'', ''ゴ''); str := replace(str, ''ザ'', ''ザ''); str := replace(str, ''ジ'', ''ジ''); str := replace(str, ''ズ'', ''ズ''); str := replace(str, ''ゼ'', ''ゼ''); str := replace(str, ''ゾ'', ''ゾ''); str := replace(str, ''ダ'', ''ダ''); str := replace(str, ''ヂ'', ''ヂ''); str := replace(str, ''ヅ'', ''ヅ''); str := replace(str, ''デ'', ''デ''); str := replace(str, ''ド'', ''ド''); str := replace(str, ''バ'', ''バ''); str := replace(str, ''ビ'', ''ビ''); str := replace(str, ''ブ'', ''ブ''); str := replace(str, ''ベ'', ''ベ''); str := replace(str, ''ボ'', ''ボ''); str := replace(str, ''パ'', ''パ''); str := replace(str, ''ピ'', ''ピ''); str := replace(str, ''プ'', ''プ''); str := replace(str, ''ペ'', ''ペ''); str := replace(str, ''ポ'', ''ポ''); str := replace(str, ''ヴ'', ''ヴ''); zenkakus := ''アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ''; hankakus := ''アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ''; len := length(zenkakus); for i in 0 .. len loop str := replace(str, substr(zenkakus, i, 1), substr(hankakus, i, 1)); end loop; return str; end; ' language 'plpgsql' ;
- 追記:20080414 id:umitanuki さんからの指摘で、「ヴ」に対応しました。ありがとうございます。特殊なのは「ヴ」だけなのかな?「ッ」も抜けてましたので追加しました。
select * from boards where kana2full(name) = 'プログラマ';
みたいに使えると思います。
注意
実際のプロジェクトの仕様が半角カナと全角カナを区別しないようにする必要が無くなってしまったこともあり、全然テストしていません。m(_ _)m
バグを指摘いただければ、このエントリを修正します。
データベースのcharsetがutf-8の状態で簡単な確認をしましたが、他のcharsetではどうなんでしょう?
「ヴ」が考慮されていないのでは。。。