SQLiteでCSVのインポート/エクスポートしたい件

データベースを使っていると、よくcsvファイルと相互に変換したくなります。MySQLやPostgreSQLでは標準でcsvのインポート/エクスポートができるので、SQLiteでも出来るだろうという事で調べてみました。

結論から言うとSQLiteで使えるCSVのインポート/エクスポートは制約が強くて使い辛いです。というのも、カラムの文字列内にセパレータ(標準ではカンマ)が含まれている場合は、クォートされていても、セパレータとして認識されてしまい、正常なcsvとして扱われないからです。(例えば”Hi, Nice to meet you.”は2カラムとして扱われます。)

ちなみにSQLite標準のインポート/エクスポートは以下のように行います。

# 標準で以下のようにインポート/エクスポートできるが、セパレータが上手くパースされない
.mode csv table_name
# エクスポート
SELECT * FROM table_name
# インポート
.import sample.csv table_name

カラム内にセパレータが無ければ標準のままで行けますが、そんな事はイチイチ考えてられないので、pythonで簡単にインポート/エクスポートを実装してみました。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sqlite3
import csv

# SQLite内のデータはutf-8を想定
def sqlite2csv(db_name, table_name, out_filename):
  dbh = sqlite3.connect(db_name)
  writer = csv.writer(file(out_filename, 'w'))
  for row in dbh.execute('SELECT * FROM %(table_name)s' % locals()):
    writer.writerow([col.encode('utf-8') if isinstance(col, unicode) else col for col in row])
  dbh.close()

# csvのセパレータはカンマを想定
def csv2sqlite(db_name, table_name, in_filename):
  dbh = sqlite3.connect(db_name)
  reader = csv.reader(open("import.csv", "rb"))
  for row in reader:
    ph = "?," * (len(row) - 1) + "?"
    dbh.execute("INSERT INTO %(table_name)s VALUES(%(ph)s)" % locals(), tuple(row))
  dbh.commit()
  dbh.close()

これでSQLiteとCSVが相互に行き来できるようになりましたね。ま、最初からMySQL/PostgreSQLを使えよというのが最もかもですが。

2 thoughts on “SQLiteでCSVのインポート/エクスポートしたい件”

  1. 私も同じようなものをこしらえました。Rubyですが。
    XML用とエクセル用のものもあれば便利なのですねーとか思いながら面倒なので結局CSVでやります。
    経費の計算みたいち小さいデータも、ウェブアクセスの分析などおおきなデータも、軽くこなしてくれるのでSQLiteは便利ですね。

Leave a Reply

Your email address will not be published. Required fields are marked *