LinuxでODBCドライバを使ってOracleに接続する

2020.10.26

こんにちは。データアナリティクス事業本部の松村です。

LinuxでOracleにODBC接続をする機会がありました。わりと良くあるニーズだと思いますので、知っていればどうということはない作業だと思いますが、意外と必要十分な手順を記したものが見つかりませんでしたので、まとめてみました。

unixODBCのインストール

ODBC接続を行うためには、各種DB製品のODBCドライバのほか、まずはODBCドライバマネージャが必要です。これはアプリケーションとODBCドライバ間の通信を管理するミドルウェアです。unixODBCがLinuxでは一般的、かつOracle純正のODBCドライバも対応を謳っているので、これをインストールします。

パッケージマネージャ経由でインストールする

unixODBCは、大抵のディストリビューションでパッケージマネージャの標準リポジトリに含まれていますので、これを使うのが簡単です。
ただし、Oracle ODBCドライバのバージョンごとに、推奨するunixODBCのバージョンが異なります。パッケージマネージャのunixODBCのバージョンがこれ未満の場合は、自己責任で標準外のリポジトリを探すか、後述するソースコードからのインストール手順をお試しください。

Oracle Instant Client ODBCインストール・ノート | Oracle 日本
(下の方に『Linux/UNIX向けunixODBCドライバ・マネージャの推奨バージョン』という章があります)

ここでは標準リポジトリからのインストールを紹介します。
ディストリビューションによってパッケージの名前がunixODBCだったりunixodbcだったりしています。私がいくつか調べた限りでは、RedHat系はunixODBC、Debian系はunixodbcでした。

RedHat系ディストリビューションの場合

$ sudo yum install unixODBC
(略)
========================================================================================
 Package                アーキテクチャー バージョン                リポジトリー    容量
========================================================================================
インストール中:
 unixODBC               x86_64           2.3.1-14.el7              base           413 k
依存性関連でのインストールをします:
 libtool-ltdl           x86_64           2.4.2-22.el7_3            base            49 k

トランザクションの要約
========================================================================================
インストール  1 パッケージ (+1 個の依存関係のパッケージ)

総ダウンロード容量: 462 k
インストール容量: 1.3 M
Is this ok [y/d/N]:

インストール確認のプロンプトの前にunixODBCのバージョンが表示されますので(上の実行例では2.3.1)、問題なければyを入力してそのままインストール、必要なバージョンより古い場合はNを入力して中断し、後述するソースコードからのインストールを実施します。

Debian系ディストリビューションの場合

まずはaptを-sオプション付きで実行して、インストールされるバージョンを確認します。

$ sudo apt -s install unixodbc
(略)
Inst libltdl7 (2.4.6-2 Ubuntu:18.04/bionic [amd64])
Inst libodbc1 (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Inst odbcinst1debian2 (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64]) []
Inst odbcinst (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Inst unixodbc (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Conf libltdl7 (2.4.6-2 Ubuntu:18.04/bionic [amd64])
Conf libodbc1 (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Conf odbcinst1debian2 (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Conf odbcinst (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])
Conf unixodbc (2.3.4-1.1ubuntu3 Ubuntu:18.04/bionic [amd64])

unixODBCのバージョンが表示されますので(上の実行例では2.3.4)、問題なければ今度はaptを-sオプションなしで実行してインストールします。必要なバージョンより古い場合、次のコマンドはスキップし、後述するソースコードからのインストールを実施します。

$ sudo apt install unixodbc

ソースコードからインストールする

準備

unixODBCをソースコードからインストールするためには、以下のようにいくつかのツールが必要です。未導入の場合はパッケージマネージャからインストールします。

  • automake
  • autoconf
  • gcc
  • libtool
  • make

ディストリビューションによってはこれらに依存関係が設定されており、どれかをインストールしたときに他のパッケージが一緒にインストールされることがあります。

RedHat系ディストリビューションの場合
$ sudo yum install automake
$ sudo yum install autoconf
$ sudo yum install gcc
$ sudo yum install libtool
$ sudo yum install make
Debian系ディストリビューションの場合
$ sudo apt install automake
$ sudo apt install autoconf
$ sudo apt install gcc
$ sudo apt install libtool
$ sudo apt install make

ソースコードのダウンロード

unixODBCのソースコードは以下の公式サイトから入手できます。

unixODBC

ソースコードはanonymous FTPとHTTPの両方で配布しています。anonymous FTPはDownloadのアイコン、HTTPはVia HTTPの後ろのリンクです。

これをcurlで取得します。通常はHTTPで良いでしょう。たまたま私がダウンロードしようとしたときはHTTPがダウンしていましたので、FTPを使いました。

anonymous FTPの場合(URLはサイトのリンクからコピーしたものを使用してください)
$ curl -u anonymous:{password} -O ftp://ftp.unixodbc.org/pub/unixODBC/unixODBC-2.3.9.tar.gz

{password}の部分には何を入力しても良いのですが、anonymous FTPでは自身のメールアドレスにするのがお作法とされています。

HTTPの場合(URLはサイトのリンクからコピーしたものを使用してください)
$ curl -L -O http://www.unixodbc.org/unixODBC-2.3.9.tar.gz

ビルドとインストール

ダウンロードしたファイルを展開します。バージョンなどファイル名の細かい違いは読み替えてください。

$ tar zxvf unixODBC-2.3.9.tar.gz

展開したディレクトリの中に入ります。バージョンなどディレクトリ名の細かい違いは読み替えてください。

$ cd unixODBC-2.3.9

Makefile(ビルドのための設定ファイル)を自動生成します。

$ ./configure

ビルドを実行します。

$ make

ビルドしたライブラリや設定ファイルなどをインストールします。

$ sudo make install

Oracle Instant Client ODBCのインストール

Oracle Instant Client ODBCをインストールします。ダウンロード時にOracle.comプロファイルへのサインインが必要ですので、基本的にcurlで直接ダウンロードすることはできません。Webブラウザからこの先の手順でダウンロードします。
GUIをインストールしていない等の理由でLinux上でWebブラウザを使えない場合は、他のコンピュータでダウンロードしてからSFTP等で転送します。

Oracle.comプロファイルのアカウントをお持ちでない方は、まずは以下の説明を読んだ上で登録してください。

Oracle.comプロファイルについて | Oracle 日本

肝心の登録方法が載っていませんが、こちらをご覧ください。

Oracle.comプロファイル(MyProfile)の作成方法を教えてください。

Oracle Instant Client ODBCのダウンロード

Oracle.comアカウントの登録が済んだら、まずは以下のリンクからOracle Instant Clientのページにアクセスします。

Oracle Instant Client - Oracle Databaseに接続するための無償のツールとライブラリ | Oracle 日本

『今すぐダウンロード』をクリックします。

移動したページは英語表記ですが、日本語に切り替えたい場合はURLのドメインの後ろに/jpを追加してください。
インストールするプラットフォームをクリックします。今回は『Instant Client for Linux x86-64』を選択しました。

インストールしたいバージョンのBasicまたはBasic Lightをダウンロードします。ZIP形式とRPM形式がありますが、RPMはOracle Linux 6または7用のパッケージのようです。ダウンロード時はOracle.comプロファイルへのサインインを求められますが、その手順は省略します。

BasicとBasic Liteの違いは、後者はエラーメッセージがすべて英語であることと、対応するキャラクタセットがUS7ASCII/WE8DEC/WE8ISO8859P1/WE8MSWIN1252およびUnicodeに限られるという点です。基本的にはBasicを選んでおくのが良いでしょう。

今回は、少し古いですがバージョン12.2.0.1.0のBasicのZIPパッケージ版で説明していきます。

もうひとつ、同じページにあるODBCドライバもダウンロードします。バージョンはBasic(Lite)と同じものを選びます。

インストール先のLinux以外のコンピュータでダウンロードした場合は、ファイルをSFTP等で転送しておきます。この手順は省略します。

Instant Client Basic(Lite)のインストール

まずはInstant Client Basic(Lite)からインストールします。手順は先ほどパッケージをダウンロードしたページの下の方の『Linux x86-64用Instant Clientのインストール(64ビット)』以下に書いてありますので、これを参考に進めていきます。
途中で出てくるコマンドにおける、バージョンなどファイル/ディレクトリ名の細かい違いは適宜読み替えてください。

パッケージの展開

インストール先のディレクトリを決めて、それがまだない場合は作成します。ここでは手順書に倣って/opt/oracleとします。
以降の作業はファイル所有者をrootにする前提でコマンドにsuを付けていますが、その必要がなければその他のユーザで作業しても構いません。

$ sudo mkdir -p /opt/oracle

Instant Client Basic(Lite)のZIPパッケージを展開します。-dオプションで展開先のディレクトリを指定します(省略時はカレントディレクトリです)。

$ sudo unzip instantclient-basic-linux.x64-12.2.0.1.0.zip -d /opt/oracle

展開したディレクトリ(/opt/oracle/instantclient_12_2のようにunzip時に出力されます)に移動します。

$ cd /opt/oracle/instantclient_12_2

シンボリックリンクの作成

Instant Client Basic(Lite)のバージョンが18.3未満の場合は、シンボリックリンクを2つ作成します。
コマンドの数字の部分は、実際に存在するファイル名のものに置き換えてください。

$ sudo ln -s libclntsh.so.12.1 libclntsh.so
$ sudo ln -s libocci.so.12.1 libocci.so

libaioのインストール

libaioパッケージをインストールします。ディストリビューションによっては(ちょっと調べた限りではDebian系がそうでした)libaio1という名前の場合もあるようです。

RedHat系ディストリビューションの場合
$ sudo yum install libaio
Debian系ディストリビューションの場合
$ sudo apt install libaio1

共有ライブラリのパス設定

他にOracle製のソフトウェアをインストールしていない場合、共有ライブラリのパスにInstant Client Basic(Lite)のインストールディレクトリを設定します。方法は2つあります。

システム全体で設定したい場合は、ldconfigを使用します。

$ sudo sh -c "echo /opt/oracle/instantclient_12_2 > /etc/ld.so.conf.d/oracle-instantclient.conf"
$ sudo ldconfig

ユーザごとに設定したい場合は、環境変数LD_LIBRARY_PATHに追加します。

$ export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2:$LD_LIBRARY_PATH

後者の方法を選択した場合、通常は~/.bash_profileにも上記コマンドと同じ内容を追加しておけば、ログイン時に自動的に環境変数が設定されます。ただし、systemdやcron等で起動したプロセスからOracleに接続する場合、通常は~/.bash_profileをロードしませんので、他の方法で環境変数LD_LIBRARY_PATHをセットしておく必要があります。アプリケーションによっては設定ファイルで環境変数をセットできるものもあります。

設定ファイル用ディレクトリの作成

tnsnames.orasqlnet.oraなどの設定ファイルを用いて接続設定を行いたい場合は、インストールディレクトリ配下のnetwork/adminディレクトリに置く必要があります。バージョンが12.2以下の場合はこのディレクトリがパッケージの展開時に作られないので、それを作成します。

$ sudo mkdir -p /opt/oracle/instantclient_12_2/network/admin

Instant Client ODBCのインストール

Instant Client ODBCのインストール手順は以下に説明がありますので、これを参考にして進めていきます。

Oracle Instant Client ODBCインストール・ノート | Oracle 日本

途中で出てくるコマンドにおける、バージョンなどファイル/ディレクトリ名の細かい違いは適宜読み替えてください。

パッケージの展開

Instant Client ODBCのZIPパッケージを展開します。-dオプションでInstant Client Basic(Lite)の展開先と同じディレクトリを指定します。

$ sudo unzip instantclient-odbc-linux.x64-12.2.0.1.0-2.zip -d /opt/oracle

展開したディレクトリ(/opt/oracle/instantclient_12_2のようにunzip時に出力されます)に移動します。

$ cd /opt/oracle/instantclient_12_2

unixODBCへのODBCドライバの登録

unixODBCにドライバを登録するときは、odbcinst.iniにドライバのパスを設定します。このファイルを直接編集したり、unixODBCに付属のodbcinstコマンドを使ったりすることができますが、Instant Client ODBCにもそのためのスクリプトが同梱されていますので、そちらを使うことにします。

まずはunixODBCの設定ファイルの場所を調べます。

$ odbcinst -j
unixODBC 2.3.9
DRIVERS............: /usr/local/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /home/centos/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

出力される内容は環境により異なります。この先の設定で必要なものだけ説明します。

DRIVERS
odbcinst.iniの場所を表しています。今回はソースコードからインストールしましたので/usr/local/etc/odbcinst.iniですが、パッケージマネージャの標準リポジトリからインストールした場合は、ほとんどが/etc/odbcinst.iniになります。
SYSTEM DATA SOURCES
システム全体で共通のデータソース設定ファイルのパスを表しています。
USER DATA SOURCES
現在のOSユーザ専用のデータソース設定ファイルのパスを表しています。

以上の値を使って設定を進めます。
Instant Client ODBCに付属するスクリプトのコマンド形式は以下のとおりです。

odbc_update_ini.sh <ODBCDM_Home> [<Install_Location> <Driver_Name> <DSN> <ODBCINI>]

各パラメータの意味は以下のとおりです。

ODBCDM_Home
必須です。unixODBCのインストールディレクトリを指定します。少し癖があって、odbcinst.iniのパスのうち、/etc/odbcinst.iniよりも前の部分(ただしパスが/etc/odbcinst.iniの場合は/)を指定します。
Install_Location
libsqora.so.12.1など、ODBCドライバが存在するディレクトリのパスです。省略した場合はカレントディレクトリを指定したものと見做されます。
Driver_Name
インストールするODBCドライバを識別するための名称です。省略した場合はOracle 12c ODBC driver(バージョンにより異なります)などが自動設定されます。
DSN
ODBCのDSN名です。省略した場合はOracleODBC-12c(バージョンにより異なります)などが自動設定されます。
ODBCINI
データソース設定ファイルのパスです。省略した場合はコマンドを実行したユーザーの~/.odbc.ini(先のodbcinstコマンドの出力結果のうちのUSER DATA SOURCESと同じです)を指定したものと見做されます。

このスクリプトは、実行するたびにodbcinst.iniへドライバのパスを、データソース設定ファイルにDSN設定を追記します。そのため、DSN設定だけを追加したい場合には向きません。
ドライバの登録をするときに一度だけ使用し、そのときに一緒に追記されたDSN設定をコピー&ペーストして新しいDNS設定を追記していくのが良いでしょう。

それではスクリプトを実行します。Driver_Nameはデフォルトにするために空文字、ODBCINIにはシステム全体で共通のデータソース設定ファイルを指定します。

$ sudo ./odbc_update_ini.sh /usr/local /opt/oracle/instantclient_12_2 "" ORCL /usr/local/etc/odbc.ini

実際に設定された内容を見てみましょう。まずはodbcinst.iniから。

$ cat /usr/local/etc/odbcinst.ini

[Oracle 12c ODBC driver]
Description     = Oracle ODBC driver for Oracle 12c
Driver          = /opt/oracle/instantclient_12_2/libsqora.so.12.1
Setup           =
FileUsage       =
CPTimeout       =
CPReuse         =

次にodbc.iniを見てみます。接続先(ServerName)の設定が空欄ですが、後で設定します。

$ cat /usr/local/etc/odbc.ini

[ORCL]
Application Attributes = T
Attributes = W
BatchAutocommitMode = IfAllSuccessful
BindAsFLOAT = F
CloseCursor = F
DisableDPM = F
DisableMTS = T
Driver = Oracle 12c ODBC driver
DSN = ORCL
EXECSchemaOpt =
EXECSyntax = T
Failover = T
FailoverDelay = 10
FailoverRetryCount = 10
FetchBufferSize = 64000
ForceWCHAR = F
Lobs = T
Longs = T
MaxLargeData = 0
MetadataIdDefault = F
QueryTimeout = T
ResultSets = T
ServerName = 
SQLGetData extensions = F
Translation DLL =
Translation Option = 0
DisableRULEHint = T
UserID = 
StatementCache=F
CacheBufferSize=20
UseOCIDescribeAny=F
SQLTranslateErrors=F
MaxTokenSize=8192
AggregateSQLType=FLOAT

ネットサービス名の登録

ODBCのDSN設定で接続先を指定しますが、そこにはネットサービス名と簡易接続ネーミングメソッドによる接続記述子が指定可能です。ネットサービス名を指定する場合は、tnsnames.oraに予め記述しておきます。

Instant Client Basic(Lite)のインストールディレクトリ配下の/network/adminディレクトリにtnsnames.oraファイルを作成し、Oracleサーバへの接続記述子を追加します。

/opt/oracle/instantclient_12_2/network/admin/tnsnames.ora

ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.2.191)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = ORCL)
    )
  )

DSN設定の登録

DSN設定は、システム全体で共通、もしくはOSユーザ専用のデータソース設定ファイルに記載することで行います。用途に応じてどちらかを選択します。

システム全体のデータソース設定ファイルに記載

odbcinst -jコマンドを実行してSYSTEM DATA SOURCESで示されるファイルを調べ、それを開きます。その中のServerNameに、先ほどtnsnames.oraに設定したネットサービス名を設定します。

/usr/local/etc/odbc.ini

[ORCL]
(略)
ResultSets = T
ServerName = ORCL
SQLGetData extensions = F
(略)
OSユーザ専用のデータソース設定ファイルに記載

ユーザ専用のファイルは~/.odbc.iniです。ここにシステム全体で共通のデータソース設定ファイルからDSN設定をひとつコピーしてきて貼り付けます。その後先頭のセクション名とDSN(この2つは揃えてください)、ServerNameを書き換えます。
例ではServerNameに簡易接続ネーミングメソッドによる接続記述子を指定してみました。

~/.odbc.ini

[ORCLPDB]
(略)
Driver = Oracle 12c ODBC driver
DSN = ORCLPDB
EXECSchemaOpt =
(略)
ResultSets = T
ServerName = 10.0.2.191:1521/ORCLPDB
SQLGetData extensions = F
(略)

環境変数NLS_LANGの設定

接続先Oracleのキャラクタセットを環境変数NLS_LANGに設定します。ここまでに設定してきた接続先OracleはAL32UTF8ですので、例ではJapanese_Japan.AL32UTF8をセットしています。 LD_LIBRARY_PATHと同じように、アプリケーションからOracleに接続する前に、接続先に応じた値がセットされるようにしておく必要があります。

$ export NLS_LANG=Japanese_Japan.AL32UTF8

接続テスト

ODBCの接続テストは、unixODBCに付属のiusqlユーティリティで行うことができます。これはコマンドラインベースの簡易的なSQLクライアントです。コマンドの形式は以下のとおりです。

iusql DSN {user}/{password}

まずはシステム全体のデータソース設定ファイルに記載したDSN(ORCL)をテストしてみます。

$ iusql ORCL SYSTEM/{password}
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL>

繋がったように見えますね。SQLを実行してみましょう。

SQL> SELECT CAST(GLOBAL_NAME AS VARCHAR2(10)) AS GLOBAL_NAME FROM GLOBAL_NAME;
+------------+

| GLOBAL_NAME|

+------------+

| ORCL       |
+------------+

SQLRowCount returns -1
1 rows fetched

結果が帰ってきました。一旦quitと入力してiusqlを終了します。

今度はOSユーザ専用のデータソース設定ファイルに記載したDSN(ORCLPDB)をテストしてみます。こちらは簡易接続ネーミングメソッドを使っていました。

$ iusql ORCLPDB SYSTEM/{password}
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> SELECT CAST(GLOBAL_NAME AS VARCHAR2(10)) AS GLOBAL_NAME FROM GLOBAL_NAME;
+------------+

| GLOBAL_NAME|

+------------+

| ORCLPDB    |
+------------+

SQLRowCount returns -1
1 rows fetched

こちらもOKです。DSNを簡易接続ネーミングメソッドで設定していても問題ありませんね。

最後に

何もわからない状態から調べ始めたので、書き上げるまでだいぶ時間がかかりましたが、作業自体は特に躓くポイントもなく単純でした。最後に確認のために、もう一度クリーンな状態のOSから作業を実施してみたのですが、10分もかからずに終わりました。
今回の内容が、これから同じ作業を始めるどなたかの助けになれば幸いです。