こんにちは。きんくまです。
だいぶ暖かくなってきましたね。
さて、オリジナルのデータベースから吐き出されたCSVのデータがあって、そこから自分の開発用にSQLiteのデータを用意したくなりました。
それでどうやってやろうかなと思ってjsでやってみました。という感じのメモです。
使ったnodeのモジュールは以下のものです。
4万件をデータをいれてみたけど、とりあえずうまく動いているみたいなので大丈夫かと思います。
コード
//設定 ========= //CSVのファイル名、同じ名称でxxxx.dbができあがる var filePrefix = 'my_csv_file'; var csvPath = './csv/' + filePrefix + '.csv'; var databasePath = './db/' + filePrefix + '.db'; //Insertするたびコンソールに出力するか。出力しない方が速い var insertLogEnable = false; //================== var parse = require('csv-parse'); var lineReader = require('line-reader'); var sqlite3 = require('sqlite3').verbose(); var db = new sqlite3.Database(databasePath); var count = 0; var startTime; function setupDatabase(callback){ var stmt = "CREATE TABLE persons (name TEXT, age INTEGER)"; db.run(stmt, callback); } function insertRow(rowArray, callback){ var stmt = ["INSERT INTO persons VALUES ("]; var maxIndex = rowArray.length - 1; rowArray.forEach(function(elem, index){ stmt.push('?'); if(index != maxIndex){ stmt.push(","); } }); stmt.push(')'); db.run(stmt.join(''), rowArray, callback); } function loadCSV(){ lineReader.open(csvPath, function(reader) { function readNextLine(){ if (reader.hasNextLine()) { reader.nextLine(function(line) { parse(line, {}, function(err, output){ var row = output[0]; insertRow(row, function(err){ if(err){ console.log('line ' + count + ' Error! ' + row[0]); console.log(err); }else if(insertLogEnable){ //insertするたびに呼ばれるコメント。出したい文言を出力する console.log('line ' + count + ' ' + row[0] + ' inserted'); } readNextLine(); }); }); }); }else{ db.close(); var lapse = (new Date()).getTime() - startTime.getTime(); lapse = lapse / 1000.0; console.log('total ' + count + ' insert complete! ' + lapse + 's'); } count++; } readNextLine(); }); } setupDatabase(function(){ startTime = new Date(); loadCSV(); });
死のピラミッドがいくつか見られますが、自分用の開発ツールなのでキニシナイ!
たくさんの行数があるものは、1度に処理するのではなくて、1行ずつ読み込んでそのたびにDBに加える処理してあげれば問題ないみたい。
なので、line-readerというモジュールで1行ずつ読み込んでいます。
====
さすがにあのピラミッドはマズいので書き直した。
//設定 ========= //CSVのファイル名、同じ名称でxxxx.dbができあがる var filePrefix = 'my_csv_file'; var csvPath = './csv/' + filePrefix + '.csv'; var databasePath = './db/' + filePrefix + '.db'; //Insertするたびコンソールに出力するか。出力しない方が速い var insertLogEnable = false; //================== var parse = require('csv-parse'); var lineReader = require('line-reader'); var sqlite3 = require('sqlite3').verbose(); var db = new sqlite3.Database(databasePath); var count = 0; var startTime; function setupDatabase(callback){ var stmt = "CREATE TABLE persons (name TEXT, age INTEGER)"; db.run(stmt, callback); } function insertRow(rowArray, callback){ var stmt = ["INSERT INTO persons VALUES ("]; var maxIndex = rowArray.length - 1; rowArray.forEach(function(elem, index){ stmt.push('?'); if(index != maxIndex){ stmt.push(","); } }); stmt.push(')'); db.run(stmt.join(''), rowArray, callback); } function parseCSVLine(line, reader){ parse(line, {}, function(err, output){ var row = output[0]; insertRow(row, function(err){ if(err){ console.log('line ' + count + ' Error! ' + row[0]); console.log(err); }else if(insertLogEnable){ console.log('line ' + count + ' ' + row[0] + ' inserted'); } readNextCSVLine(reader); }); }); } function readNextCSVLine(reader){ if (reader.hasNextLine()) { reader.nextLine(function(line) { parseCSVLine(line, reader); }); }else{ db.close(); var lapse = (new Date()).getTime() - startTime.getTime(); lapse = lapse / 1000.0; console.log('total ' + count + ' insert complete! ' + lapse + 's'); } count++; } function loadCSV(){ lineReader.open(csvPath, readNextCSVLine); } setupDatabase(function(){ startTime = new Date(); loadCSV(); });
==
余談なんだけど、SQLのstatementとqueryって何が違うのかって調べたらわかりやすく書いてあった。
>> Difference between a statement and a query in SQL
つまり、こんな感じかな。
StatementはDBの何らかの操作をするとき。(CRUDとかテーブルの構造作ったりとか)
Queryは何かの値を取得するとき(SELECT)のStatementの別名。DBの情報自体に変更はない。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ