知らないとチョットつまづく RDS for Oracle の NLS パラメータ

今回は RDS for Oracle へ移行される際に、知らないとチョットつまづきそうな NLS パラメータについて、つまづいた人が紹介してみようかと思います。

NLS パラメータってなんだっけ?

National Language Support(NLS)は、ロケール固有のニーズをサポートするための機能です。例えば、日付、時刻、通貨単位、カレンダーの規則などが、各国の言語やロケールに自動的に適応されます。通常は、Oracle サーバーの初期化パラメータで日本環境にセットし利用されているかと思います。RDS for Oracle では、初期化パラメータの設定にパラメータグループを使用しますが、パラメータグループで指定可能な NLS パラメータは下表のとおり、一部に制限されています。

パラメータ パラメータグループ設定可否 RDSデフォルト値 日本環境の値 デフォルト値
NLS_LANGUAGE 不可 AMERICAN JAPANESE NLS_LANGから導出
NLS_TERRITORY 不可 AMERICA JAPAN NLS_LANGから導出
NLS_CURRENCY 不可 $ Y NLS_TERRITORYから導出
NLS_ISO_CURRENCY 不可 AMERICA JAPAN NLS_TERRITORYから導出
NLS_NUMERIC_CHARACTERS 不可 ., ., NLS_TERRITORYから導出
NLS_CHARACTERSET 不可 AL32UTF8 AL32UTF8 AL32UTF8
NLS_CALENDAR 不可 GREGORIAN GREGORIAN なし。暗黙的にGREGORIAN
NLS_DATE_FORMAT 可能 DD-MON-RR RR-MM-DD NLS_TERRITORYから導出
NLS_DATE_LANGUAGE 不可 AMERICAN JAPANESE NLS_TERRITORYから導出
NLS_SORT 不可 BINARY BINARY NLS_LANGUAGEから導出
NLS_TIME_FORMAT 可能 HH.MI.SSXFF AM HH24:MI:SSXFF NLS_TERRITORYから導出
NLS_TIMESTAMP_FORMAT 可能 DD-MON-RR HH.MI.SSXFF AM RR-MM-DD HH24:MI:SSXFF NLS_TERRITORYから導出
NLS_TIME_TZ_FORMAT 可能 HH.MI.SSXFF AM TZR HH24:MI:SSXFF TZR NLS_TERRITORYから導出
NLS_TIMESTAMP_TZ_FORMAT 可能 DD-MON-RR HH.MI.SSXFF AM TZR RR-MM-DD HH24:MI:SSXFF TZR NLS_TERRITORYから導出
NLS_DUAL_CURRENCY 不可 $ ¥ NLS_TERRITORYから導出
NLS_COMP 不可 BINARY BINARY BINARY
NLS_LENGTH_SEMANTICS 可能 BYTE BYTE BYTE
NLS_NCHAR_CONV_EXCP 可能 FALSE FALSE FALSE
NLS_NCHAR_CHARACTERSET 不可 AL16UTF16 AL16UTF16 AL16UTF16

多くの値が NLS_TERRITORYNLS_LANGUAGE の値によって導出されていますので、これらのパラメータだけ設定できれば良さそうなのですが、「パラメータグループ設定可否」の列に注目すると、これら2つの値を初期化パラメータとして設定することは出来ないのです。

NLS_LANG をクライアント側の環境変数で指定しよう!

では、NLS_TERRITORYNLS_LANGUAGE は変更できないのか、というとそんなコトはありません。あくまで初期化パラメータとして設定できないだけであり、ALTER SESSION コマンドで変更することは可能です。ただし、ALTER SESSION の場合、接続の都度変更しなければならないので、それは面倒ですよね。なので、クライアント側の環境変数にするのがオススメです。クライアント側の環境変数で指定されている場合は、初期化パラメータの値はオーバーライドされます。

NLS_LANG で指定する

環境変数にセットする場合、NLS_TERRITORYNLS_LANGUAGE をそれぞれ指定する必要はありません。これらの値を導出するための NLS_LANG を指定します。今回は、bash_profile に設定してみたいと思います。NLS_LANG を指定する構文はNLS_LANG = language_territory.charset となります。

export NLS_LANG=JAPANESE_JAPAN.AL32UTF8

これだけで OK です!

NLS_LANG を指定しない場合、どうなる

例えば、オンプレミスおよび Oracle on EC2 の環境の場合、多くの環境は初期化パラメータで日本環境にあわせた日付、時刻フォーマットを利用されていると思います。これらの環境から、デフォルトパラメータの RDS for Oracle へ Export/Import すると、Import 時に日付フォーマットが異なるため以下のようなエラーになります。

ORA-39083: Object type TABLE:"xxxx"."xxxxxx" failed to create with error:
ORA-01861: literal does not match format string

あくまで一例ですので、その他にもいろいろ不都合はあるかと思います。

さいごに

既知の方には「そりゃ、そうだろ」な内容かと思いますが、クライアント側での NLS 環境変数をこれまで意識されていない方は、ちょっと躓くポイントかと思いましたのでシェアいたしました。

以上、大阪オフィスの丸毛でした!