mokky14's IT diary

IT関係の仕事メモ、勉強会の感想など書いてます。

PythonからOracle接続

PythonOracle接続してデータ検索する方法のメモ。

環境

OS Python Oracle Client
CentOS 6.4 3.3.0 11.2.0.3.0

インストール

Oracleへの接続ライブラとして、cx_Oracleをインストールする。
Oracleクライアントは既にインストールされている環境を使用したので、そちらのインストールは省略。(多分以下の4つのrpmをインストールした環境のはず)

まずは、cx_Oracleインストールに必要なpython3-develのインストール。

$ sudo yum install python3-devel
読み込んだプラグイン:fastestmirror, refresh-packagekit, security
インストール処理の設定をしています
Loading mirror speeds from cached hostfile
 * PUIAS_6_computational: puias.math.ias.edu
 * base: ftp.iij.ad.jp
 * centosplus: centos.mirror.secureax.com
 * epel: epel.mirror.srv.co.ge
 * extras: centos.mirror.secureax.com
 * updates: ftp.iij.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> Package python3-devel.x86_64 0:3.3.0-1.puias6 will be インストール
--> 依存性解決を終了しました。

依存性を解決しました

===================================================================================================================
 パッケージ                アーキテクチャ     バージョン                   リポジトリー                       容量
===================================================================================================================
インストールしています:
 python3-devel             x86_64             3.3.0-1.puias6               PUIAS_6_computational             169 k

トランザクションの要約
===================================================================================================================
インストール         1 パッケージ

総ダウンロード容量: 169 k
インストール済み容量: 532 k
これでいいですか? [y/N]y
パッケージをダウンロードしています:
python3-devel-3.3.0-1.puias6.x86_64.rpm                                                     | 169 kB     00:01
rpm_check_debug を実行しています
トランザクションのテストを実行しています
トランザクションのテストを成功しました
トランザクションを実行しています
  インストールしています  : python3-devel-3.3.0-1.puias6.x86_64                                                1/1
  Verifying               : python3-devel-3.3.0-1.puias6.x86_64                                                1/1

インストール:
  python3-devel.x86_64 0:3.3.0-1.puias6

完了しました!

続いて、cx_Oracleのインストール。

$ echo $ORACLE_HOME
/usr/lib/oracle/11.2/client64
$ sudo ln -s /usr/include/oracle/11.2/client64 $ORACLE_HOME/include
$ su
# echo /usr/lib/oracle/11.2/client64/lib >> /etc/ld.so.conf.d/oracle.conf
$ sudo ldconfig
$ pip install cx_Oracle
(途中略)
Successfully installed cx-Oracle
Cleaning up...

環境設定(クライアント環境)

自分の環境のOracle周りの設定。 LD_LIBRARY_PATHの設定は必須。 他は関係ない設定もあると思うけどメモがてら載せとく。

export ORACLE_HOME=/usr/lib/oracle/11.2/client64
TNS_ADMIN=$ORACLE_HOME/network/admin
export TNS_ADMIN
export NLS_LANG=Japanese_Japan.AL32UTF8
NLS_DATE_FORMAT='YYYYMMDDHH24MISS'
export NLS_DATE_FORMAT
NLS_TIMESTAMP_FORMAT='YYYYMMDDHH24MISS.FF3'
export NLS_TIMESTAMP_FORMAT

export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=.:$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib

データ取得

テーブルからデータを取得して表示してみた。

$ python3
Python 3.3.0 (default, Feb 12 2013, 17:01:04)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>> conn=cx_Oracle.connect('scott','tiger','xx.xx.xx.xx/tns_service_name')
>>> cur=conn.cursor()
>>> sql="select * from scott.db_tbl  where rownum<20"
>>> cur.execute(sql)
<cx_Oracle.Cursor on <cx_Oracle.Connection to scott@xx.xx.xx.xx/tns_service_name>>
>>> rows=cur.fetchmany(10)
>>> print(len(rows))
10
>>> print(cur.rowcount)
10
>>> for row in rows:
...  print(row)
...
(tupleデータ10行出力)
>>> rows=cur.fetchmany(10)
>>> print(len(rows))
9
>>> print(cur.rowcount)
19
>>> for row in rows:
...  print(row)
...
(tupleデータ9行出力)
>>> rows=cur.fetchmany(10)
>>> print(len(rows))
0
>>> print(cur.rowcount)
19
>>> cur.close()
>>> conn.close()

この内容を元にして、テーブルレコード全件をCSVファイルに出力するPythonスクリプト作ってみた。

#!/usr/bin/python3

import cx_Oracle
import sys
import csv
from itertools import chain

argvs = sys.argv
argc = len(argvs)
if argc != 2:
  print('Usage: %s TableName' % argvs[0])
  quit()

table_name = argvs[1].upper()
file_name = table_name + '_data.csv'

with cx_Oracle.connect('scott','tiger','xx.xx.xx.xx/tns_service_name') as conn:
  # テーブルの列名取得
  column_name_sql = 'select column_name from user_tab_columns where table_name = :tbl'
  cur_columns = conn.cursor()
  cur_columns.execute(column_name_sql, tbl=table_name)
  columns = cur_columns.fetchall()
  cur_columns.close()
  columns = tuple(chain.from_iterable(columns))

  # テーブルのレコード全件取得
  data_sql = 'select * from %s' % table_name
  cur_data = conn.cursor()
  cur_data.execute(data_sql)
  with open(file_name, 'w') as f:
    csv_writer = csv.writer(f)
    csv_writer.writerow(columns)
    while 1:
      rows = cur_data.fetchmany(50)
      if len(rows) == 0:
        break
      csv_writer.writerows(rows)
  cur_data.close()

参考:
pythonからOracleに接続するための拡張モジュール、cx_Oracleの基本的な使い方 at nkjmkzk.net
UbuntuでPythonからcx_Oracleモジュールを使ってOracle Database 11gに接続する - 偏った言語信者の垂れ流し
Cursor Object — cx_Oracle 5.1.3 documentation