Skip to content

Latest commit

 

History

History
299 lines (199 loc) · 9.69 KB

53ed08bcf53b0936f0c6.md

File metadata and controls

299 lines (199 loc) · 9.69 KB
title tags author slide
WindowsでSQL*Plusを使う
oracle 文字化け Windows
dameyodamedame
false

WindowsでSQL*Plusを使う記事でchcpを勧めている記事がいくつかあり、最近も見かけてコメントしたら消えてしまったので、少し書いておこうかと思います。

例) https://qiita.com/bearbutler/items/a46b1c51aa74e2c99e7d

個人的にはあまりオススメしないので。

文字化け現象の説明

まずはとあるホストhost_aでサービス名xepdb1という名前のoracleが動いているとします。そこにWindowsPCからSQL*Plusを使って接続してDB操作をしようという話です。ここでは以前書いた記事の環境にWindowsから繋ぐ想定で説明します。

https://qiita.com/dameyodamedame/items/4ab7a2c595bb1c00f53e#oracle

Windows側の環境構築

https://www.oracle.com/jp/database/technologies/instant-client/winx64-64-downloads.html

ここにある最新のOracleクライアントのBasicパッケージとSQL*Plus パッケージをダウンロードして、zipを展開し、同じ名前のフォルダ(instantclient_バージョン番号)を統合してどこかに展開します(ここではC:\instantclient_21_9とします)。

現象の再現

コマンドプロンプトを起動して以下の操作をします。

C:\>cd instantclient_21_9
C:\instantclient_21_9>sqlplus SYSTEM/pass@host_a/xepdb1

SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

Last Successful login time: xxx

Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> select 'ほげ' from dual;

'????'
------------
????

SQL> exit
Disconnected from Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

selectの結果が化けていますね。

原因と対策

「sqlplus 文字化け site:.oracle.com」でGoogle検索(日本語)すると

https://docs.oracle.com/cd/E57425_01/121/SQPUG/GUID-E26A730D-C5B1-4CB3-BB2F-07E526B547C0.htm

が出てきます。つまりWindowsでは環境変数NLS_LANGを、Japanese_Japan.JA16SJISにする必要があるということです(Japanese_Japan.JA16SJISTILDEが良いとする資料もありましたが、Oracleから明示的に推されている資料を見つけられませんでした)。個人的にはJapanese_Japan.JA16SJISTILDEの方が良いと思います(理由などは以下に記載されています)が、本記事内ではJapanese_Japan.JA16SJISで統一しています。

https://www.idearu.info/article/data/ds1083

対策の効果確認

c:\instantclient_21_9>set NLS_LANG=Japanese_Japan.JA16SJIS
c:\instantclient_21_9>sqlplus.exe SYSTEM/pass@localhost/xepdb1

SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: xxx

Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL> select 'ほげ' from dual;

'ほげ'
------------
ほげ

SQL> exit
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0との接続が切断されました。

メッセージが日本語で表示されるようになり、select結果の文字化けもなくなりました。

chcpを使う方法

紹介されている方法は上記現象の対策として以下を実施します。

  • 環境変数NLS_LANGにJapanese_Japan.UTF8を設定
  • chcp 65001を実施

対策の効果確認

コマンドプロンプト(cmd.exe+conhost.exe)の場合

c:\instantclient_21_9>set NLS_LANG=Japanese_Japan.UTF8
c:\instantclient_21_9>chcp 65001
Active code page: 65001
c:\instantclient_21_9>sqlplus.exe SYSTEM/pass@localhost/xepdb1

SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: xxx


Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL> select 'ほげ' from dual;

'@@'
------
@@

SQL> exit
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0との接続が切断されました。

メッセージなどの日本語は大丈夫ですが、肝心のselect結果が化けてしまっています。

PowerShell(powershell.exe+conhost.exe)の場合

PS C:\instantclient_21_9> $Env:NLS_LANG = "Japanese_Japan.UTF8"
PS C:\instantclient_21_9> .\sqlplus.exe SYSTEM/pass@localhost/xepdb1

SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: xxx


Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL> select 'ほげ' from dual;

'��'
------------------
��

SQL> exit
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0との接続が切断されました。

コマンドプロンプトと同様メッセージなどの日本語は大丈夫ですが、肝心のselect結果が化けてしまっています。

結果

対策不十分です。

なぜchcpをしているのか?

Japanese_Japan.JA16SJISは名前のとおりシフトJISしか使えず、例えばハングル文字の안녕하십니까には該当コードがありません。Japanese_Japan.AL32UTF8にするとUTF-8が使えるようになり、これらの文字も使える

https://docs.oracle.com/cd/G11854_01/nlspg/supporting-multilingual-databases-with-unicode.html#GUID-EB57AB68-A390-4814-81DD-6B78D33310CC

のですが、コマンドプロンプトやPowerShellの端末のデフォルト設定では(コードページが932=シフトJISなので)これらの文字を表示することが出来ません。この設定を変えるコマンドがchcpで、

https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/chcp

65001はutf-8を表しています。

https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers

なので、oracleが返したUTF-8のコードはここで調べた範囲では正しく表示できています。

何が問題だったのか?

端末からUTF-8のつもりで読み込んだコードが正しくOracleに伝わっていないからです。例えば先程のselect文を以下に変更すると表示できます。

SQL> select unistr('\307b\3052') as str from dual;

STR
--------
ほげ

SQL>

回避策は?

リダイレクトやパイプを使うことです。これらを使えば端末のエンコーディング設定に煩わされることがありません。事前にUTF-8で書かれたSQLファイルを用意します。

select 'ほげ' from dual;
C:\instantclient_21_9>sqlplus.exe SYSTEM/pass@localhost/xepdb1 <hoge.sql

SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: xxx

Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL>
'ほげ'
------
ほげ

SQL> Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0との接続が切断されました。

ただどうせリダイレクトするなら、出力もリダイレクトでいいわけで…

C:\instantclient_21_9>sqlplus.exe SYSTEM/pass@localhost/xepdb1 <hoge.sql >hoge.log

そうなると端末の設定など意味がないので、chcpもする必要がなくなります(unicodeを扱いたいならAL32UTF8の設定だけは必要です)。

さきほどのハングルやサロゲートペアになる絵文字まで試すと…

select 'ほげ' from dual;
select '안녕하십니까' from dual;
select '😀' from dual;
C:\instantclient_21_9>sqlplus.exe SYSTEM/pass@localhost/xepdb1 <hoge2.sql >hoge2.log
SQL*Plus: Release 21.0.0.0.0 - Production on xxx
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: xxx


Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
に接続されました。
SQL> 
'ほげ'
------
ほげ

SQL> 
'안녕하십니까'
------------------
안녕하십니까

SQL> 
'😀'
----
😀

SQL> Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0との接続が切断されました。

問題ないようです。ただし、

https://www.oracle.com/jp/database/technologies/faq-nls-lang.html

WindowsにOracle Unicodeクライアントはありますか。 ... Oracleデータベースに含まれるUnicode対応のクライアントは、iSQL*Plusのみです。 ...

まとめ

  • 現状Windowsでは原則シフトJISで動作させるのが好ましそう
  • Unicode文字が必要ならUTF-8もありだが、chcpでは入力が出来ないので注意
  • FAQによると(Windowsの)Oracleデータベースに含まれるUnicode対応のクライアントは、iSQL*Plusのみとのこと

あとがき(ポエム)

個人的にシフトJIS推しなわけではありません。Oracleもそうで、MSのせいで仕方ないという体に見えます。MSはMSで互換性、引いてはユーザーのために仕方なくと言いそうな気もします。いつかシステムロケールがUTF-8になって至るところが燃え上がる(?)まではこの状況が続きそうなので、いざというとき火を吹かないよう、確実な部分を見極めつつ徐々に対応していくべきだと思います。