SqliteでCSVインポート

sqliteでCSVファイルをインポートする方法と注意点です。

インポートしたいのは以下の reservation テーブル。

sqlite> .schema reservation
CREATE TABLE RESERVATION (
    ID integer primary key autoincrement, -- autoincrementなしはdelete後再利用される。問題ないとは思うが念のため付与する。
    STATUS char(2),  -- AC:受付中, OK:確定, NG:先約ありNG, CA:キャンセル
    -- フォーム
    CHECKIN_DATE date, -- localtime で格納
    CHECKIN_TIME integer, -- 時のみ
    CHECKOUT_DATE date, -- localtime で格納
    NUM_DORMITORY integer, -- ドミトリー人数
    NUM_WOMAN_ONLY_DORMITORY integer, -- 女性専用ドミトリー人数
    NUM_PRIVATE_ROOM_A integer, -- 個室A人数
    NUM_PRIVATE_ROOM_B integer, -- 個室B人数
    NAME varchar(256), -- 名前(漢字)
    NAME_KANA varchar(256), -- 名前(かな)
    TEL varchar(20), -- 電話番号
    MAIL_ADDRESS varchar(256), -- メールアドレス
    USE_PARKING boolean, -- 駐車場使用有無
    MESSAGE varchar(1024), -- 連絡事項
    --
    MEMO varchar(1024), -- メモ
    CREATED_AT timestamp default (datetime('now','localtime')),
    MODIFIED_AT timestamp default (datetime('now','localtime'))
    );

評価用のデータを作成しようと、「テストデータ・ジェネレータ」というありがたいツールでデータを作成し、Excelにコピペして、ほかのデータも適当に作ってCSVファイルに保存しました。

sqlite でCSVをインポートする方法はこんなかんじ。

$ sqlite3 hogedb.sqlite3
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> .mode csv
sqlite> .separator ,
sqlite> .import /tmp/reservation.csv reservation
sqlite> 

でもそう簡単にはいかなくて、こんなエラーが出まくります。

/tmp/reservation.csv:1: expected 18 columns but found 11 - filling the rest with NULL
/tmp/reservation.csv:1: INSERT failed: datatype mismatch
/tmp/reservation.csv:2: expected 18 columns but found 11 - filling the rest with NULL
/tmp/reservation.csv:2: INSERT failed: datatype mismatch
/tmp/reservation.csv:3: expected 18 columns but found 11 - filling the rest with NULL
/tmp/reservation.csv:3: INSERT failed: datatype mismatch
              :

「expected 18 columns but found 11」のほうはほっといてもいいんですが、行末に不足分の「,」を追加すると出なくなりました。

「INSERT failed: datatype mismatch」のほうがやっかいで、文字列をダブルクォートで囲んだりしてみましたが、どの列のデータが悪いのかもわからないため四苦八苦しました。

最終的に、1行だけのCSVファイルを作成し、後ろから1列ずつ消していったのですが、最後に残ったIDが空だったのが悪かったようです。だめだったのがこれ↓。「OK」の前、最初の列(ID)が空だったのが原因。

,OK,"2021-07-11",19,"2021-07-13",1,0,0,0,"笠原 久江","カサハラ ヒサエ","090-3474-7472","kasahara1219@tokyo24.com",1,,,,

IDはPKだから insert するときは自動生成してくれます。.import でインポートするときも自動生成してくれるものと思い込んでいたのですが、してくれませんでした。

CSVの編集はEmacsの replace-regexp でダブルクオートで囲ったり、行末にコンマを追加したりしましたが、IDを連番で入れるには、M-:(eval-expression)で以下の式を評価して実行しました。(M-< で先頭行に行ってから。)

(let ((l 1)) (while (not (eobp)) (beginning-of-line)(insert (format "%d" l))(setq l (1+ l))(forward-line 1)))

date型も注意が必要です。ダブルクォートなしの「2021-07-11」でインポートしたら「2003」が入りました。そりゃそうだ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です