はじめに
ここではLinux上のユーザープログラムが、同じくLinux上で稼働するDBMSにODBC経由で接続するための手順を示す。前提とするプラットフォームおよびDBMSは以下のとおり。
- プラットフォームおよびDBMS
PostgreSQL 17.2 (w/ unixODBC 2.3.9) + AlmaLinux 9.5
PostgreSQL 17.5 (w/ unixODBC 2.3.12) + AlmaLinux 10.0
MariaDB 11.4 (w/ unixODBC 2.3.9) + AlmaLinux 9.6
MySQL 8.4 (w/ unixODBC 2.3.12) + AlmaLinux 10.0 - ユーザープログラムが稼働するOS : DBMSと同じOS
- ユーザープログラムを構成する技術 : gccで作成したネイティブアプリ
ユーザープログラムとDBMSの関係
ユーザープログラムは、何らかのConnectorを介してDBMSに接続する。DBMSごとに多種のConnectorが提供されており、ODBCはそのひとつであり、代表的なものとなる。
ODBC経由でDBMSに接続するには、DBMSの開発元から提供されているODBC Driverを予めクライアント側(ユーザープログラム側の環境)に組み込んでおく必要がある。また、ユーザープログラムは、ODBC Driver Managerを介してODBC Driverに接続する。

Windowsの場合、ODBC Driver Managerは、OSに組み込まれているため、その存在を特別意識しなくても良かったが、Linuxの場合、ODBC Driverと同様に、ODBC Driver Managerもクライアント側に組み込んでおく必要がある。
Linux用のODBC Driver Managerとしては、下記のものがよく知られている。
unixODBC
- 概要: 最も一般的で広く使用されているオープンソースのODBC Driver Manager。
- 特徴: 多くのODBC Driverやアプリケーションでサポートされている。
- 利用シーン: 多くのLinuxディストリビューションにおける標準のODBC Driver Manager。
- ライセンス: GNU General Public License (GPL) および GNU Lesser General Public License (LGPL)
iODBC (Independent Open DataBase Connectivity)
- 概要: unixODBCと同様にオープンソースのODBC Driver Manager。最初にリリースされたODBC Driver Managerひとつで、クロスプラットフォーム対応を目指してる。
- 特徴: macOSや他のUnix系システムでも広く使用されている。
- 利用シーン: 特定の商用アプリケーションやiODBCに特化した環境で使われることがある。
- ライセンス: BSD License
環境構築
ユーザープログラムがODBC経由でDBMSに接続するための環境構築手順を示す。DBMSのインストールについては、数多くの情報源があり、その設定方法も様々であるため、ここでは詳細を事細かに示すことはせず、最低限の記載にとどめる。また、ODBC Driver Managerについては、unixODBCを使用する。
PostgreSQL 17.2 (w/ unixODBC 2.3.9) + AlmaLinux 9.5
PostgreSQLの最低限の動作に必要な、下記のパッケージをダウンロードする。
postgresql17-libs-17.2-1PGDG.rhel9.x86_64.rpm
postgresql17-17.2-1PGDG.rhel9.x86_64.rpm
postgresql17-server-17.2-1PGDG.rhel9.x86_64.rpm
postgresql17-odbc-17.00.0004-1PGDG.rhel9.x86_64.rpm
上記は、PostgreSQLの公式サイトからダウンロード可能である。
https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-9-x86_64/
また、unixODBCは、RPMのダウンロードサイトからダウンロード可能である。
unixODBC-2.3.9-4.el9.x86_64.rpm
unixODBC-devel-2.3.9-4.el9.x86_64.rpm
ダウンロード後、下記のコマンドでインストールする。インストールする順番を間違えるとエラーとなる。
$ sudo rpm -ivh postgresql17-libs-17.2-1PGDG.rhel9.x86_64.rpm
$ sudo rpm -ivh postgresql17-17.2-1PGDG.rhel9.x86_64.rpm
$ sudo rpm -ivh postgresql17-server-17.2-1PGDG.rhel9.x86_64.rpm
$ sudo rpm -ivh unixODBC-2.3.9-4.el9.x86_64.rpm
$ sudo rpm -ivh unixODBC-devel-2.3.9-4.el9.x86_64.rpm
$ sudo rpm -ivh postgresql17-odbc-17.00.0004-1PGDG.rhel9.x86_64.rpm
PostgreSQLおよびunixODBCのインストール後、PostgreSQLおよびunixODBCの初期設定を行う。postgresユーザーでinitdbを実行する。コマンド実行時にpostgresユーザーのパスワードの設定を求められる。ここではパスワード=postgresとする。
$sudo su - postgres
$ /usr/pgsql-17/bin/initdb -E UTF8 --locale=C -A scram-sha-256 -W
postgresユーザーのまま、/var/lib/pgsql/17/data/pg_hba.confが下記のようになっていることを確認する。
local all all scram-sha-256
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
同じく/var/lib/pgsql/17/data/postgresql.confを下記のように編集する。
listen_address='localhost'
port=5432
このあと、postgresユーザーをexitで抜けて下記を実行する。
$ sudo systemctl start postgresql-17.service
$ sudo systemctl enable postgresql-17.service
postgresユーザーとして、psqlでデータベース、テーブル、レコードを追加する。
$ psql -U postgres
# create database testdb;
# \l
... testdbを含むデータベース一覧が表示される ...
# \c testdb
# create table abc (id integer, name varchar(255));
# insert into abc values (0, 'hello');
上記で、\l はデータベース一覧を表示するコマンドで、\cはデータベースに接続するコマンドである。
postgresユーザーでのpsqlの実行後、psqlを抜けて、/etc/odbc.iniおよび/etc/odbcinst.iniを変更する。
# odbcinst.ini:
[PostgreSQL]
Driver=/usr/pgsql-17/lib/psqlodbcw.so
Setup=/usr/lib64/unixODBC/libodbcpsqlS.so
Driver64=/usr/pgsql-17/lib/psqlodbcw.so
Setup64=/usr/lib64/unixODBC/libodbcpsqlS.so
FileUsage=1
※/usr/lib64/unixODBC/libodbcpsqlS.soは、構成によっては存在しない場合があります。
# odbc.ini:
[PostgreSQL_DS]
Driver=PostgreSQL
Database=testdb
Servername=localhost
Port=5432
UserName=postgres
Password=postgres
下記isqlでtestdbに接続し、abcテーブルの情報を参照できることを確認する。
$ isql PostgreSQL_DS
SQL> select * from abc;
PostgreSQL 17.5 (w/ unixODBC 2.3.12) + AlmaLinux 10.0
PostgreSQLの最低限の動作に必要な、下記のパッケージをダウンロードする。
postgresql17-libs-17.5-3PGDG.rhel10.x86_64.rpm
postgresql17-17.5-3PGDG.rhel10.x86_64.rpm
postgresql17-server-17.5-3PGDG.rhel10.x86_64.rpm
postgresql17-odbc-17.00.0005-1PGDG.rhel10.x86_64.rpm
上記は、PostgreSQLの公式サイトからダウンロード可能である。
https://download.postgresql.org/pub/repos/yum/17/redhat/rhel-10-x86_64/
また、unixODBCは、RPMのダウンロードサイトからダウンロード可能である。
unixODBC-2.3.12-6.el10.x86_64.rpm
unixODBC-devel-2.3.12-6.el10.x86_64.rpm
ダウンロード後、下記のコマンドでインストールする。インストールする順番を間違えるとエラーとなる。
$ sudo rpm -ivh postgresql17-libs-17.5-3PGDG.rhel10.x86_64.rpm
$ sudo rpm -ivh postgresql17-17.5-3PGDG.rhel10.x86_64.rpm
$ sudo rpm -ivh postgresql17-server-17.5-3PGDG.rhel10.x86_64.rpm
$ sudo rpm -ivh unixODBC-2.3.12-6.el10.x86_64.rpm
$ sudo rpm -ivh unixODBC-devel-2.3.12-6.el10.x86_64.rpm
$ sudo rpm -ivh postgresql17-odbc-17.00.0005-1PGDG.rhel10.x86_64.rpm
以降の設定は、"PostgreSQL 17.2 (w/ unixODBC 2.3.9) + AlmaLinux 9.5"のセクションを参照のこと。
MariaDB 11.4 (w/ unixODBC 2.3.9) + AlmaLinux 9.6
MariaDBの最低限の動作に必要な、下記のパッケージをダウンロードする。
mariadb-11.4.5-rhel-9-x86_64-rpms.tar
mariadb-connector-odbc-3.2.4-rhel9-amd64.rpm
boost-program-options-1.75.0-10.el9.x86_64.rpm
上記は、MariaDBの公式サイト(以下)およびRPMのダウンロードサイトからダウンロード可能である。
https://dlm.mariadb.com/browse/mariadb_server/11.4.5/yum/rhel/
https://dlm.mariadb.com/browse/odbc_connector/3.2.4/
また、unixODBCは、RPMのダウンロードサイトからダウンロード可能である。
unixODBC-2.3.9-4.el9.x86_64.rpm
unixODBC-devel-2.3.9-4.el9.x86_64.rpm
ダウンロード後、tarを解凍し、下記のコマンドでインストールする。
$ sudo rpm -ivh MariaDB-shared-11.4.5-1.el9.x86_64.rpm MariaDB-common-11.4.5-1.el9.x86_64.rpm
$ sudo rpm -ivh MariaDB-client-11.4.5-1.el9.x86_64.rpm
$ sudo rpm -ivh boost-program-options-1.75.0-10.el9.x86_64.rpm
$ sudo rpm -ivh galera-4-26.4.21-1.el9.x86_64.rpm
$ sudo rpm -ivh MariaDB-server-11.4.5-1.el9.x86_64.rpm
$ sudo rpm -ivh unixODBC-2.3.9-4.el9.x86_64.rpm
$ sudo rpm -ivh unixODBC-devel-2.3.9-4.el9.x86_64.rpm
$ sudo rpm -ivh mariadb-connector-odbc-3.2.4-rhel9-amd64.rpm
インストールに際して下記の点に注意のこと。
- インストールする順番を間違えるとエラーとなる。
- 事前にPerl (cpanモジュール)をインストールする必要あり。
$ cpan install File::Copy
$ cpan install Sys::Hostname )
MariaDBおよびunixODBCのインストール後、MariaDBおよびunixODBCの初期設定を行う。
$sudo vi /etc/my.cnf.d/server.cnf
...
[mysqld]
character-set-server = utf8mb4
$ sudo vi /etc/my.cnf.d/client.cnf
...
[client]
default-character-set=utf8mb4
MariaDBのサービスを起動し、MariaDBの設定を行う。
$ sudo systemctl start mariadb
$ sudo systemctl enable mariadb
$ sudo mariadb-secure-installation
mariadb-secure-installationでは、クエリに対して、すべて空リターンで返答。rootユーザーのパスワードとして”root”を指定。
rootユーザーとしてmariadbコマンドを起動し、データベース、テーブル、レコードを追加する。
$ mariadb -u root -p
Enter password:
MariaDB [(none)]> create database testdb;
MariaDB [(none)]> show databases;
... testdbを含むデータベース一覧が表示される ...
MariaDB [(none)]> connect testdb;
MariaDB [(none)]> create table abc (id integer, name varchar(255));
MariaDB [(none)]> insert into abc values (0, ‘hello’);
rootユーザーで上記を実行後、mariadbコマンドを終了し、/etc/odbc.iniおよび/etc/odbcinst.iniを変更する。
# odbcinst.ini:
[MariaDB]
Driver=/usr/lib64/libmaodbc.so
DESCRIPTION=MariaDB ODBC Connector
Threading=0
UsageCount=1
# odbc.ini:
[MariaDB_DS]
Driver=MariaDB
Server=localhost
Uid=root
Pwd=root
Database=testdb
下記isqlでtestdbに接続し、abcテーブルの情報を参照できることを確認する。
$ isql MariaDB_DS
SQL> select * from abc;
MySQL 8.4 (w/ unixODBC 2.3.12) + AlmaLinux 10.0
MySQLの最低限の動作に必要な、下記のパッケージをダウンロードする。
mysql-8.4.6-1.el10.x86_64.rpm-bundle.tar
mysql-connector-odbc-9.4.0-1.el10.x86_64.rpm
mysql-connector-odbc-setup-9.4.0-1.el10.x86_64.rpm
上記は、MySQLの公式サイト(以下)からダウンロード可能である。
https://dev.mysql.com/downloads/mysql/
https://dev.mysql.com/downloads/connector/odbc/
また、unixODBCは、RPMのダウンロードサイトからダウンロード可能である。
unixODBC-2.3.12-6.el10.x86_64.rpm
unixODBC-devel-2.3.12-6.el10.x86_64.rpm
ダウンロード後、tarを解凍し、下記のコマンドでインストールする。
$ sudo rpm -ivh mysql-community-common-8.4.6-1.el10.x86_64.rpm mysql-community-client-plugins-8.4.6-1.el10.x86_64.rpm mysql-community-libs-8.4.6-1.el10.x86_64.rpm mysql-community-client-8.4.6-1.el10.x86_64.rpm mysql-community-icu-8.4.6-1.el10.x86_64.rpm
mysql-community-server-8.4.6-1.el10.x86_64.rpm
$ sudo rpm -ivh unixODBC-2.3.12-6.el10.x86-64.rpm
$ sudo rpm -ivh unixODBC-devel-2.3.12-6.el10.x86-64.rpm
$ sudo rpm -ivh mysql-connector-odbc-9.4.0-1.el10.x86-64.rpm
$ sudo rpm -ivh mysql-connector-odbc-setup-9.4.0-1.el10.x86-64.rpm
MySQLのインストール後、下記のコマンドでMySQLのサービスを起動する。
$ sudo systemctl start mysqld
$ sudo systemctl enable mysqld
起動時に一時パスワードの設定されたrootユーザーが作成される。一時パスワードは下記で取得可能。
$ grep 'temporary password' /var/log/mysqld.log
rootユーザーでmysql(SQLシェル)を起動し、パスワードを変更する。パスワードを変更しないと、mysqlでのコマンド実行が拒絶される。
$ mysql -uroot -p
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '<new password>';
データベース、テーブル、レコードを追加する。
$ mysql -uroot -p
mysql> create database testdb;
mysql> connect testdb;
mysql> create table abc (id integer, name varchar(255));
mysql> insert into abc values (0, ‘hello’);
rootユーザーで上記を実行後、mysqlコマンドを終了し、/etc/odbc.iniおよび/etc/odbcinst.iniを変更する。
# odbcinst.ini:
[MySQL ODBC 9.4 Unicode Driver]
DRIVER=/usr/lib64/libmyodbc9w.so
SETUP=/usr/lib64/libmyodbc9S.so
UsageCount=1
# odbc.ini:
[MySQL_DS]
Driver=MySQL ODBC 9.4 Unicode Driver
Server=localhost
USER=root
PASSWORD=xxxx
Database=testdb
下記isqlでtestdbに接続し、abcテーブルの情報を参照できることを確認する。
$ isql MySQL_DS
SQL> select * from abc;
ユーザープログラム
下記のプログラムは、DBMSに接続し、切断するだけのサンプルコードである。下記でコンパイルおよび実行することができる。
$ gcc testdb.cpp -lodbc -lodbcinst -o testdb
$ ./testdb
#include <cstdlib>
#include <cstdio>
#include <sql.h>
#include <sqlext.h>
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
// Return 0: Success, -1:Error
int open_database(SQLCHAR* connect_str, SQLCHAR statemsg[10], SQLCHAR msg[1024])
{
SQLINTEGER native; // This will not be refered from anywhere
SQLSMALLINT actual_msg_len; // This will not be refered from anywhere
// Alloc environment handle
if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv) == SQL_ERROR) {
if (henv != SQL_NULL_HENV) {
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, statemsg, &native, msg, 1024, &actual_msg_len);
}
return -1;
}
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, reinterpret_cast<SQLPOINTER>(SQL_OV_ODBC3), 0);
// Alloc DB connection handle
if (SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc) == SQL_ERROR) {
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
// SQLDriverConnect
SQLCHAR conn_out[255]; // This will not be refered from anywhere
SQLSMALLINT conn_out_len; // This will not be refered from anywhere
SQLRETURN Ret = SQLDriverConnect(hdbc, NULL, connect_str, SQL_NTS, conn_out, 255, &conn_out_len, SQL_DRIVER_COMPLETE);
if (Ret == SQL_ERROR || Ret == SQL_SUCCESS_WITH_INFO) {
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
// Alloc statement handle
if (SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt) == SQL_ERROR) {
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
return 0;
}
// Return 0: Success, -1:Error
int close_database(SQLCHAR statemsg[10], SQLCHAR msg[1024])
{
SQLINTEGER native; // This will not be refered from anywhere
SQLSMALLINT actual_msg_len; // This will not be refered from anywhere
// Free statement handle
if (SQLFreeHandle(SQL_HANDLE_STMT, hstmt) == SQL_ERROR) {
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
// SQLDisconnect
SQLRETURN Ret = SQLDisconnect(hdbc);
if (Ret == SQL_ERROR || Ret == SQL_SUCCESS_WITH_INFO) {
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
// Free DB connection handle
if (SQLFreeHandle(SQL_HANDLE_DBC, hdbc) == SQL_ERROR) {
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
// Free environment handle
if (SQLFreeHandle(SQL_HANDLE_ENV, henv) == SQL_ERROR) {
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, statemsg, &native, msg, 1024, &actual_msg_len);
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
SQLCHAR statemsg[10];
SQLCHAR msg[1024];
SQLCHAR connect_str[64] = "DSN=PostgreSQL_DS;";
if (open_database(connect_str, statemsg, msg) == -1) {
printf("statemsg=%s, msg=%s\n", (char*)statemsg, (char*)msg);
return -1;
}
if (close_database(statemsg, msg) == -1) {
printf("statemsg=%s, msg=%s\n", (char*)statemsg, (char*)msg);
return -1;
}
printf("success!\n");
return 0;
}
接続文字列の指定では、前述PostgreSQLに対するisqlの実行と同様にodbc.iniで設定したデータソース名'PostgreSQL_DS'を指定しているが、odbc.iniおよびodbcinst.iniに記載した個別設定をconnet_strに指定することもできる。
SQLCHAR connect_str[128] = "Driver=/usr/pgsql-17/lib/psqlodbcw.so;Server=127.0.0.1;Database=testdb;UID=postgres;PWD=postgres;Port=5432;";