plpgsql 全角カナ 半角カナ 比較

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ではどうなんでしょう?

1件のコメント

  • 「ヴ」が考慮されていないのでは。。。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください