[PR]今日のニュースは
「Infoseek モバイル」


DB-APIを使ったテキストファイルからのデータのインポート

 主なRDBMSには、データをテキストファイルからテーブルにロード (インポート)するツールが付属しています。 例えばMS Accessには「外部データの取り込み」、 OracleにはSQL*Loader、PostgreSQLにはpsqlの\copyコマンド、 MySQLにはSQL*Loaderの文法によく似たLOAD DATA INFILE ... INTOコマンド、 等々ですが、これらはRDBMSによってツールも使い方も随分違います。 そこで、先に出てきたPython DB APIのカーソルのカラム情報を利用して、 Pythonで汎用的なデータのインポートツールを作ってみました。 下のソースプログラムがそのモジュール(Importer.py)です。

import string

""" *****************************************************************
SQL文を作成して返します。paramstyleが?(qmark)のDBモジュールでないと
使えません。
パラメータ:
  table_name ... 対象のテーブル名
  cur        ... 対象のテーブルを(SELECT * FROM ...)
                 というSQL文でexecuteした直後のカーソル
戻り値:
  INSERT文(SQL文)の文字列。カラムの数だけプレースホルダーとして'?'
  が含まれます。
""" *****************************************************************
def __create_sql(table_name, cur):
  seq = cur.description

  sql = 'INSERT INTO ' + table_name + ' ('
  count = 0
  #print "カラムの数:" + str(len(seq))
  for col in seq:
    (name, type_code, display_size, internal_size,
     precision, scale, null_ok) = col
    if count > 0: sql += ', '
    sql += name
    count += 1
    if count % 5 == 4: sql += "\n"
  sql += ') VALUES ('
  for i in range(0, count):
    if i > 0: sql += ', '
    sql += '?'
    if i % 5 == 4: sql += "\n"
  sql += ')'
  return sql

""" *****************************************************************
データファイルをテーブルにロードします。
パラメータ:
  table_name ... 対象のテーブル名
  cur        ... 対象のテーブルを(SELECT * FROM ...)
                 というSQL文でexecuteした直後のカーソル
                 クローズされていないこと。
  datafilename ... データファイル名。各カラムの区切り子はタブ
                   文字です。
戻り値:
 追加した行数(正の整数)
特記:
  コミットは呼び出し側で行ってください。
""" *****************************************************************
def importFile(table_name, cur, datafilename):
  sql = __create_sql(table_name, cur)
  fin = open(datafilename, "r")
  buf = fin.readline()

  rowcount = 0
  while buf != "":
    # string.stripを使うと末尾のカラムが空白の場合、
    # 連続するタブ文字も削除されてしまうので、厳密に改行文字だけを
    # 削除しています。
    buf = string.replace(buf, "\n", "")
    params = string.split(buf, "\t")
    ####print "パラメータの数:" + str(len(params))
    # ""はNoneに変換
    for i in range(0, len(params)):
      if(params[i] == ""): params[i] = None
    # 行追加実行
    cur.execute(sql, params)
    rowcount += 1

    # 次の行を読む
    buf = fin.readline()
  fin.close()
  return rowcount
# end.

ソース中にも書いていますが、モジュール名.paramstyleが「qmark」(?) であるDBモジュールでないと使えません。 つまり、kinterbasdbやzxJDBCなどなら使えますが、 MySQLDB(paramstyle=format)などでは使えません。

 以下は、そのモジュールを使って、 タブ区切りのテキストファイル "orders.txt" からテーブルDWH_ORDERS にデータをインポートするスクリプトです。

import kinterbasdb
import Importer

con = kinterbasdb.connect(dsn="localhost:c:/usr/dbms/fb/udb.gdb",
  user="urano", password="urano399", charset="SJIS")
cur = con.cursor()
sql = "SELECT * FROM DWH_ORDERS WHERE CHUBAN = 'dummy'"
cur.execute(sql)

n = Importer.importFile("DWH_ORDERS", cur, "orders.txt")
print str(n) + "行のデータを追加しました。"
con.commit()
cur.close()
con.close()
# end.

セクションのサブメニューに戻る
(first uploaded 2003/02/16 last updated (not ever))