2024.08.07
AWS Summit Japanに行ったらクラウドインフラが「インフラ」ではないことを実感した
2020.07.21
プログラミング【Oracle】LISTAGG関数の暗黙の文字コード変換について
こんにちは。ZYです。
今回は、Oracle Databaseの集計関数である「LISTAGG」で暗黙的に行われている文字コード変換と、そのバージョンごとの差異についてです。
LISTAGGは、以下みたいな形で使うのですが、
この時、「Oracleのバージョンが古い」かつ「対象とするカラム(LAST_NAME)がNVARCHAR」だと、結果が文字化けします。
LISTAGG(LAST_NAME, '/') WITHIN GROUP (ORDER BY LAST_NAME) AS LAST_NAME_LIST
ちなみに、Oracleのバージョンが12.1だと文字化けして、バージョン18cだと文字化けしませんでした。
なぜそんなことが起こるのか。
公式ドキュメントによると、この場合のLISTAGGの戻りデータ型はVARCHAR2になります。
メジャー列がRAW型である場合、戻り値のデータ型はRAWです。そうでない場合、戻りデータ型はVARCHAR2です。
カラムLAST_NAMEはNVARCHARなので、NVARCHAR→VARCHAR2への変換が行われている、ということになります。
そして、Oracleはデフォルトだと、以下のように文字コードが設定されています。
VARCHAR2 = AL32UTF8
NVARCHAR2 = AL16UTF16
どうやらNVARCHAR→VARCHAR2に変換する際のUTF16→UTF8への文字コード変換が、Oracle12.1は行われず、Oracle18だと暗黙的に行われているのが原因みたいです。
手元にあったバージョンが12.1と18cなので、それ以外は試せていませんが、この間のバージョンで暗黙の文字コード変換が入るようになったようです。
(公式ドキュメントやパッチノートを見ても、この文字コード変換に関する記述が見当たらなかったので、あくまで予想です)
では、古いOracle12.1では、どうすればいいかというと、以下のようにconvertで明示的に文字コード変換を行ってやると、文字化けを避けれます。
LISTAGG(CONVERT(LAST_NAME, 'UTF8'), '/') WITHIN GROUP (ORDER BY LAST_NAME) AS LAST_NAME_LIST
最新バージョンでは対象のデータ型をほとんど意識せずに使えるようになっているので問題になることはあまりないかと思いますが、古いバージョンのOracleを使っている場合は参考にしてみてください。
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
タグ検索