検証環境
- Oracle Cloud利用
- Oracle Linux 7.7 (VM.Standard2.1)
- Python 3.6
- cx_Oracle 7.3
- Oracle Database 19.5 (ATP, 1OCPU)
- Oracle Instant Client 18.5
はじめに
過去の連載では日本語データを取り扱わない形で進めていました。ですが、この連載をご覧になるほとんどの方は、日本語環境で仕事をしていて、日本語データのOracle Databaseをご利用されていると思われます。今回は日本語が格納されているテーブルのSELECTを文字化けさせずに取り扱う方法を解説します。
事前準備
SQL*Plus, SQL Developer等を使用して、以下のスクリプトを流してください。日本語データの入っている、既存のテーブルを代用いただいても構いません。
create table sample05a (col1 varchar2(50));
insert into sample05a values('日本オラクル株式会社');
commit;
NLS_LANG
サンプルとして以下のアプリケーションを用意しました。
事前準備で別のテーブルを用意された方は、1列目に日本語データの列が指定される形でSELECT文を変更して実行してください。その場合、このサンプルアプリケーションは1行しか表示しないので、WHERE句で主キー指定で1件に絞り込むなり、最初の1行に行数制限するなりの措置も実施していただけると、余計な処理時間を取りません。
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = "select * from sample05a"
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
print((cursor.execute(SQL).fetchone())[0])
一般的にOracle Databaseにアクセスするアプリケーションを稼働させる際に日本語への対応が必要な場合、大抵の環境では環境変数NLS_LANGを設定する必要があります。cx_Oracleにおいても、バージョン7.3まではNLS_LANGは有効です。バージョン8以降については後述します。上記アプリケーションをNLS_LANGの有無で比較したのが以下になります。
$ echo $LANG
en_US.UTF-8
$ echo $NLS_LANG
$ python sample05b.py
??????????
$ export NLS_LANG=japanese_japan.al32utf8
$ python sample05b.py
日本オラクル株式会社
NLS_LANG設定前は「??????????」と、データが正しく表示できていません。
Oracle Databaseでは、DBとクライアント間の文字コード変換ができない場合は「?」を表示します。NLS_LANGを設定した後は正しく表示できています。
encoding引数
cx_Oracleには、NLS_LANGとは別に、接続時(cx_Oracleのconnect()メソッド)の引数encodingに、文字エンコーディングの指定が可能です。encoding引数のデフォルトはバージョン7.3まではNoneで、何も設定されていません。バージョン8からはUTF-8がデフォルトとなり、環境変数NLS_LANGのキャラクタセットの指定は無視されます。なお、バージョン8以降においても、キャラクタセット以外の設定は有効です。
Python3においてはUTF-8が標準なので、バージョン7.3まではencodingにUTF-8を指定して接続すれば(バージョン8以降はエンコーディングの指定なしで)、NLS_LANGの設定がなくとも日本語データの表示が可能です。とはいえ、例えばOracle Databaseのエラーメッセージを日本語で受け取りたい場合はNLS_LANGが必要です。また、SQL*PlusなどPython以外のアプリケーションへの考慮も必要です。
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION, encoding="UTF-8") as connection:
変更履歴
- 2020/6/28 バージョン8での仕様変更を含んだ形に改定