Mac+Node.jsでデータベースを使いたい。〜SQLite3のインストールからサンプルまで〜

Node.jsでデータベースを使うにはどうしたらいいのだろう？

ということで、
データベースSQLite3をインストールしてnodeコマンドで実行できるサンプルまでをメモった

Nodeはすでにインストール済みとします。
Nodeの設定は[macでNode.jsの環境設定](http://qiita.com/tagosaku324/items/bf1fe149c38c99728c72)参照

# Node.jsでSQLite3を使う準備
参考資料：
1. [node.jsでsqlite3を使う方法。インストールから実装サンプルまで。苦労点も。](http://www.yoheim.net/blog.php?q=20120415)
2. [SQLite3をNode.jsで使う](http://kawamurakaeru.lolipop.jp/scw/blog/2016/06/16/sqlite3%E3%82%92node-js%E3%81%A7%E4%BD%BF%E3%81%86/)

## OSにsqlite3インストール
macだと元々入ってるみたいです。バージョン確認をしてみました。

```
$ sqlite3 -version
3.8.10.2 2015-05-20 18:17:19 2ef4f3a5b1d1d0c4338f8243d40a2452cc1f7fe4
$ which sqlite3
/usr/bin/sqlite3
```
Ubuntuだったり、他のOSだったりはsqlite3がインストールされていないかもしれませんので、インストールしてください。

```:例
$ sudo apt-get install libsqlite3-dev
```
[参考資料１](http://www.yoheim.net/blog.php?q=20120415)をみると、**`「インストールするsqlite3のバージョンが3.6以上でないとだめ。・・バージョンが低いと、後続のインストール処理で依存関係の解消ができず失敗・・」`**とありましたので、バージョンには注意が必要のようです。

## node-sqlite3のインストール
nodeでsqlite3 を使用する場合、node-sqlite3のインストールが必要です。

```
$ npm install sqlite3

> sqlite3@3.1.8 install /Users/***/NodeSampleTmp/use_sqllite/node_modules/sqlite3
> node-pre-gyp install --fallback-to-build

[sqlite3] Success: "/Users/***/NodeSampleTmp/use_sqllite/node_modules/sqlite3/lib/binding/node-v48-darwin-x64/node_sqlite3.node" is installed via remote
/Users/***/NodeSampleTmp/use_sqllite
└─┬ sqlite3@3.1.8 
  ├── nan@2.4.0 
  └─┬ node-pre-gyp@0.6.31 
    ├─┬ mkdirp@0.5.1 
    │ └── minimist@0.0.8 
:
:
npm WARN use_sqllite No README data
npm WARN use_sqllite No license field.
$ 
```
無事にsqlite3が使用できるようになったのかを確認するため、[npmサイト sqlite3](https://www.npmjs.com/package/sqlite3)のサンプルを実行してみます。

```sample.js
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');　//ファイル名を":memory:"とすると、インメモリデータベースを構築。

db.serialize(function() {
  db.run("CREATE TABLE lorem (info TEXT)");

  var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
  for (var i = 0; i < 10; i++) {
      stmt.run("Ipsum " + i);
  }
  stmt.finalize();

  db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
      console.log(row.id + ": " + row.info);
  });
});

db.close();
```
```
$ node sample.js 
1: Ipsum 0
2: Ipsum 1
3: Ipsum 2
4: Ipsum 3
5: Ipsum 4
6: Ipsum 5
7: Ipsum 6
8: Ipsum 7
9: Ipsum 8
10: Ipsum 9
$
```
実行できました。DBは作られていません。
ちなみに、
*npm install sqllite3* しないでテストスクリプトを実行したらエラーになりました。
*require('sqlite3')*が読み込めないからですね。。

```:コンソール
$ node sample.js 
module.js:440
    throw err;
    ^
Error: Cannot find module 'sqlite3'
    at Function.Module._resolveFilename (module.js:438:15)
    at Function.Module._load (module.js:386:25)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/***/NodeSampleTmp/use_sqllite/sample.js:1:77)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
```

サンプルスクリプトでSQLite3のモジュールの取り込み方がわかったので、sample.js　をカスタマイズ。[参考資料１](http://www.yoheim.net/blog.php?q=20120415)[参考資料2](http://kawamurakaeru.lolipop.jp/scw/blog/2016/06/16/sqlite3%E3%82%92node-js%E3%81%A7%E4%BD%BF%E3%81%86/)

```sample2.js
// sqlite3を使う準備
var sqlite3 = require('sqlite3').verbose();
// :memory:を指定すると揮発性のDB
// DBファイルを指定して、永続化したDBにする
var db = new sqlite3.Database('test.sqlite'); //データベースを新規に開く

// serialize関数を使うと、それぞれの行が実行されたら、次の行が実行される。
// parallel関数を用いることで、平行実行もできる。
db.serialize(function () {
  // テーブル作成
  //※　"IF NOT EXISTS"の部分は同名のテーブルが無い場合は、このままテーブルを作成。
  //既に同名テーブルがある時は何も処理せず終了。
  db.run('CREATE TABLE IF NOT EXISTS items(name, value)');

  // データ登録
  var stmt = db.prepare('INSERT INTO items VALUES(?,?)');
  for (var i = 0; i < 10; i++)
    stmt.run(["items " + i, 5 * i]);
  stmt.finalize();

  // データを更新
  var stmt2 = db.prepare("UPDATE items SET name = ? WHERE name = ?");
  for (var i = 0; i < 10; i+=3)
    stmt2.run("items 10" + i, "items " + i);
  stmt2.finalize();

  // データをコンソールに出力、参照する。
  // 引数(row)のプロパティに、SELECT句で指定した要素がある。「row.name」等で値を取得
  db.each("SELECT rowid AS id, * FROM items", function (err, row) {
    console.log(row.id + " : " + row.name + ":" + row.value);
  });
});
// DBを閉じる
db.close();
```
```:コンソール
$ node sample2.js 
1 : items 100:0
2 : items 1:5
3 : items 2:10
4 : items 103:15
5 : items 4:20
6 : items 5:25
7 : items 106:30
8 : items 7:35
9 : items 8:40
10 : items 109:45
$
```
最初の０〜１０のINSERTデータ登録の後、３つおきにnameがUPDATE登録で更新されたことがわかります。

ファイルに落とした場合実行場所に *test.sqlite* ができました。
中身の確認

```:コンソール
$ sqlite3 test.sqlite
SQLite version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for usage hints.
sqlite> .tables
items
sqlite> .schema items
CREATE TABLE items(name, value);
sqlite> select * from items;
items 100|0
items 1|5
items 2|10
items 103|15
items 4|20
items 5|25
items 106|30
items 7|35
items 8|40
items 109|45
sqlite> .exit
$
```
入ってる入ってる。
sqlite3の使い方の参考に・・・[sqlite3 コマンド](https://hydrocul.github.io/wiki/commands/sqlite.html)

さて、データ登録の仕方がわかったところで、データベースを利用した何かを作ってみよう。。