半角カタカナを全角ひらがな、全角カタカナに変換する

Oracle で過去のシステムとの結合度が低い、新規の業務システム を開発するとなった場合。
そこで、半角カタカナを採用するのはあまり望ましくない。(半角カタカナの使用について 参照)
既存の旧システムからデータ提供を受ける場合にも、投入時に変換するように調整できないかクライアントと相談するなどの努力をしてみることをお勧めする。

半角カタカナから全角文字への変換関数

半角カタカナから全角文字変換関数は Oracleの標準 SQL の機能では用意されていない(※1)。 そのため、TRANSLATE 関数REPLACE 関数 を併用した ストアド・ファンクション にて実装する。

(※1) Oracle 10g R2 から UTL_I18N パッケージ(※2) に文字列用変換 UTL_I18N.TRANSLITERATE 関数が用意されている。

SELECT UTL_I18N.TRANSLITERATE ('あイう', 'kana_hiragana') FROM DUAL ;

(※2) I18N は国際化の意味で InternationalizatioN の略 参考 ⇒ I18N (Wikipedia.org) 外部リンク

標準関数である、TO_MULTI_BYTE は、シングルバイト文字をマルチバイトに変換する関数であるが、 半角カタカナは常に マルチバイト文字列 として扱われるため、 データベース・キャラクタセットの種類を問わず変換されない。

TO_MULTI_BYTE('abcdef') ⇒ 'abcdef' ... OK
TO_MULTI_BYTE('012345') ⇒ '012345' ... OK
TO_MULTI_BYTE('アイウ') ⇒ 'アイウ'       ... NG
                 ↑           ↑ 全角表示されてますが、半角として見てください

ファンクションの仕様

ファンクション名:TO_FULL_KANA
第 1パラメータ変換したい文字列
第 2パラメータ変換するタイプ ['HIRA'|'KANA'] (省略時 'HIRA')
 └ 'HIRA'=平仮名 , 'KANA'=カタカナ
戻り値変換した文字列
制限入出力の最大文字列長は 2000 バイトまで

この例では ストアドファンクションと ローカル・サブプログラム で作成しています。もし、必要であればパッケージにしてください。相当数を呼び出す予定がある場合にはパッケージ化し変換テーブルを非公開のグローバル変数化した方が効率が良いでしょう。ソースコードが長くなるので通常のファンクションで書いています。

使用例

SELECT
	TO_FULL_KANA('ゥ゙ェ゙ェ゙ーッ' , 'HIRA')
  FROM  DUAL;
-- 結果:ぅ゛ぇ゛ぇ゛ーっ
 
SELECT
	TO_FULL_KANA('ゥ゙ェ゙ェ゙ーッ' , 'KANA')
  FROM  DUAL;
-- 結果:ゥ゛ェ゛ェ゛ーッ
 
SELECT
	TO_FULL_KANA('トウキョウトッキョキョカキョク')
  FROM  DUAL;
-- 結果:とうきょうとっきょきょかきょく

プロシージャのソース

下のソースコードの、半角カタカナ(半角の半濁点、濁点含む)は全角カタカナに変更してあるため、コピーしても正常に動作しませんので注意してください。
また、実際に使っているものではないのでバグがありましたら個々で改修お願いします。
キャラクタマップは、逆変換も想定して作成しているので全角から半角の逆変換も実装できると思います。

対象ファイル名漢字コード
プロシージャファイルfileto_full_kana.sql.2Shift JIS
CREATE OR REPLACE FUNCTION RIVUS.TO_FULL_KANA(
	P_SOURCE_STR VARCHAR2,
	P_TO_CHARSET VARCHAR2 :='HIRA'
)
RETURN VARCHAR2
IS
	/*********************************************************************/
	-- $Id: to_full_kana.sql,v 1.1 2005/06/18 00:11:59 rivus Exp $
	-- スクリプト名 :TO_FULL_KANA
	-- パラメータ   :(I  ) P_SOURCE_STR	変換文字列
	--              :(I  ) P_TO_CHARSET	変換キャラクタセット
	-- 戻り値       :変換後の文字列
	-- 特記事項     :入力および出力結果文字列長は 2000 バイトまで
	/*********************************************************************/
	TYPE  CHAR_MAP_T IS TABLE OF VARCHAR2(30);
	-- 半角カタカナ(本来は半角カナですが、すべて全角にしてあります)
	HANDAKU_KANA_HALF CHAR_MAP_T := CHAR_MAP_T(
	'パ', 'ピ', 'プ', 'ペ', 'ポ','゜'
	);
	DAKU_KANA_HALF CHAR_MAP_T := CHAR_MAP_T(
	'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 
	'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ', 
	'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 
	'バ', 'ビ', 'ブ', 'ベ', 'ボ',
	'ヴ', '゛'
	);
	KANA_HALF CHAR_MAP_T := CHAR_MAP_T(
	'アイウエオ', 'カキクケコ', 'サシスセソ', 'タチツテト', 'ナニヌネノ',
	'ハヒフヘホ', 'マミムメモ', 'ヤユヨ',     'ラリルレロ', 'ワヲン',
	'ァィゥェォ', 'ッャュョー', 'イイエカケ'
	);
	-- 全角ひらがな
	HANDAKU_HIRA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'ぱ', 'ぴ', 'ぷ', 'ぺ' ,'ぽ', '゜'
	);
	DAKU_HIRA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'が', 'ぎ', 'ぐ', 'げ', 'ご', 
	'ざ', 'じ', 'ず', 'ぜ', 'ぞ', 
	'だ', 'ぢ', 'づ', 'で', 'ど', 
	'ば', 'び', 'ぶ', 'べ', 'ぼ',
	'う゛', '゛' 
	);
	HIRA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'あいうえお', 'かきくけこ', 'さしすせそ', 'たちつてと', 'なにぬねの',
	'はひふへほ', 'まみむめも', 'やゆよ',     'らりるれろ', 'わをん',
	'ぁぃぅぇぉ', 'っゃゅょー', 'ヰゐゑヵヶ'
	);
	-- 全角カタカナ
	HANDAKU_KANA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'パ', 'ピ', 'プ', 'ペ', 'ポ','゜'
	);
	DAKU_KANA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'ガ', 'ギ', 'グ', 'ゲ', 'ゴ', 
	'ザ', 'ジ', 'ズ', 'ゼ', 'ゾ', 
	'ダ', 'ヂ', 'ヅ', 'デ', 'ド', 
	'バ', 'ビ', 'ブ', 'ベ', 'ボ',
	'ヴ', '゛'
	);
	KANA_FULL CHAR_MAP_T := CHAR_MAP_T(
	'アイウエオ', 'カキクケコ', 'サシスセソ', 'タチツテト', 'ナニヌネノ',
	'ハヒフヘホ', 'マミムメモ', 'ヤユヨ',     'ラリルレロ', 'ワヲン',
	'ァィゥェォ', 'ッャュョー', 'イイエヵヶ'
	);
	vKANA_HIRA	VARCHAR2(10);
	vOUT_STR	VARCHAR2(2000);
 
	PROCEDURE ONE_BY_ONE(
		P_STR IN OUT VARCHAR2
		,P_SRCMAP CHAR_MAP_T
		,P_DSTMAP CHAR_MAP_T
	)
	IS
	BEGIN
		FOR i IN 1..P_SRCMAP.COUNT
		LOOP
			P_STR := REPLACE(P_STR, P_SRCMAP(i), P_DSTMAP(i));
		END LOOP;
	END;
BEGIN
	vKANA_HIRA := UPPER(P_TO_CHARSET);
	vOUT_STR := P_SOURCE_STR;
	IF (INSTR(vOUT_STR,'゜') != 0) THEN
		IF (vKANA_HIRA = 'HIRA') THEN
			ONE_BY_ONE(vOUT_STR, HANDAKU_KANA_HALF, HANDAKU_HIRA_FULL);
		ELSE
			ONE_BY_ONE(vOUT_STR, HANDAKU_KANA_HALF, HANDAKU_KANA_FULL);
		END IF;
	END IF;
	IF (INSTR(vOUT_STR,'゛') != 0) THEN
		IF (vKANA_HIRA = 'HIRA') THEN
			ONE_BY_ONE(vOUT_STR, DAKU_KANA_HALF, DAKU_HIRA_FULL);
		ELSE
			ONE_BY_ONE(vOUT_STR, DAKU_KANA_HALF, DAKU_KANA_FULL);
		END IF;
	END IF;
 
	FOR i IN 1..KANA_HALF.COUNT
	LOOP
		IF (vKANA_HIRA = 'HIRA') THEN
			vOUT_STR := TRANSLATE(vOUT_STR, KANA_HALF(i), HIRA_FULL(i));
		ELSE
			vOUT_STR := TRANSLATE(vOUT_STR, KANA_HALF(i), KANA_FULL(i));
		END IF;
	END LOOP;
	RETURN vOUT_STR;
END;
/


関連事項

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ オラクルサポートセンター