環境
- Nodejs 12
やりたいこと
Nodejsを使ってMySQLに接続したい。今どきのasync / awaitを使っていい感じに書きたい。というかコールバック書きたくない
インストール
有名なのは mysql なのだが、mysql2というのもある。
すごく昔にsidorares/nodejs-mysql-nativeがあったが開発終了、mysql2として1からコードを書き直したとのこと。mysqlとAPIの互換性があり、派生いわく「パフォーマンスは本家より優れている」とのこと。
せっかくなので今回はmysql2を使ってみる。
接続
async/awaitを使う上でのポイントは、通常の require('mysql2')
だとコールバックしか使えないので require('mysql2/promise')
でrequireする必要がある。一方promiseでrequireした場合はコールバックは使えない。
以下接続してselectするまでのサンプルコード
const mysql = require('mysql2/promise'); (async () => { const connection = await mysql.createConnection( { host:'127.0.0.1', user: 'user', password: 'pass', database: 'xxxxxx' } ); try { const sql = 'select * from users limit 10'; const [rows, fields] = await connection.query('select * from users'); for (const val of rows) { console.log(val.id, val.name); } } catch(e) { console.log(e); } finally { connection.end(); } })();
あとは必ず終了時に connection.end();
をしないと終了されない。
プレースホルダーを使う
SQL中に ?
を書き、SQLのあとに値を渡すと自動でエスケープしたSQLを生成して投げてくれる。
const [rows, fields] = await connection.query('select * from users where id = ?', 2);
mysql.formatを使うとどんなSQLが生成されるのか確認できる。
console.log(mysql.format('select * from users where id = ?', 2)); // => select * from users where id = 2
レコードの追加
インサートする場合も同様に書けばおk。特にobjectをそのまま渡すことができる。
const user = {id: 10, name: 'taro'}; const res = await connection.query('INSERT INTO users SET ?', user); console.log(res);
一括レコードの追加
複数で渡す時は INSERT INTO xxx SET
は使えないので INSERT INTO xxx VALUES
構文を使う。一工夫必要で、
const users = [ {id: 5, name: 'taro'}, {id: 6, name: 'ziro'} ]; const res = await connection.query(`INSERT INTO users (${Object.keys(users[0])}) VALUES ?`, [users.map(x => Object.values(x))]); console.log(res);
のようにすると
INSERT INTO users (id,name) VALUES (5, 'taro'), (6, 'ziro')
のSQLが発行され無事1回のSQLで2レコードが一括で追加される。