インストール

npm install mysql

コネクション

var mysql      = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret'
}); //これは省略してもoK。
connection.connect();

コネクションでもエラー処理とかしたいならこんな感じ

connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
} console.log('connected as id ' + connection.threadId);
});

クエリ 其の壱

connection.query('SELECT * FROM `books` WHERE `author` = "David"', function (error, results, fields) {

})

resultは結果。fieldsは各フィールドの詳細。
filedsの中身はこんな感じ

[{"catalog":"def","db":"hoge","table":"books","orgTable":"books","name":"ID","orgName":"ID","charsetNr":63,"length":11,"type":3,"flags":16899,"decimals":0,"zeroFill":false,"protocol41":true},・・・・

クエリ 其の弐 プレースホルダーを使ったクエリ

connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], function (error, results, fields) {
}); //insert
connection.query("insert into posts ?",{title:'post'},function
(error,results,fields){
}); //複数カラムがあっても1つの?でOKなinsertの書き方
connection.query("insert into posts set ?",{title:'post',content:'content'},function
(error,results,fields){
}); //複数行insertするなら
connection.query('insert into hoge(NAME) values(?),(?),(?)',['fuga','fuga','fuga'],function(error,results,fields){
});

第一引数のSQL文中にクエスチョンマークを指定。
第二引数に配列を指定してあげると、?に入る。
この時第二引数で渡した値はエスケープされる。
第一引数で渡した文字列はエスケープされないので値はプレースホルダで渡すほうがよさそう

もし自前でエスケープするなら、下記が使える
mysql.escape()connection.escape() または pool.escape()

クエリ 其の参 オプションで指定

connection.query({
sql: 'SELECT * FROM `books` WHERE `author` = ?',
timeout: 40000, // 40s
values: ['David']
}, function (error, results, fields) {
});

jQueryの$.ajaxみたいなもんですね。
こっちのほうが見た目がすっきりしてます。

クエリ 其の四 フィールド名にもプレイスホルダーを使う

フィールド名に使う場合、??を使います

var userId = 1;
var columns = ['username', 'email'];
var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId], function(err, results) {
// ...
});

これをSQL文で書くとこうなる

SELECT username,email FROM users WHERE id = 1;

クエリ 其の五 プリペアリングクエリ?

プリペアードステートメントみたいな感じですかね?

var sql = "SELECT * FROM ?? WHERE ?? = ?";
var inserts = ['users', 'id', userId];
sql = mysql.format(sql, inserts);

これもすっきり書けていいですね。

クエリ 其の六 カスタムフォーマット

connection.config.queryFormat = function (query, values) {
if (!values) return query;
return query.replace(/\:(\w+)/g, function (txt, key) {
if (values.hasOwnProperty(key)) {
return this.escape(values[key]);
}
return txt;
}.bind(this));
}; connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });

うまく説明できないですが、上のコードの通りです。

挿入したレコードのIDを取得する

connection.query('INSERT INTO posts SET ?', {title: 'test'}, function(err, result) {
if (err) throw err; console.log(result.insertId);
});

複数挿入した場合は一番最後のIDが返ります。

挿入、更新、削除したレコード数を取得する

connection.query('DELETE FROM posts WHERE title = "wrong"', function (err, result) {
if (err) throw err; console.log('deleted ' + result.affectedRows + ' rows');
})

こっちはUpdateの際に使う

connection.query('UPDATE posts SET ...', function (err, result) {
if (err) throw err; console.log('changed ' + result.changedRows + ' rows');
})

affectedRowsとの違いは、changedRowsは変更がなかった行は含まれない点
affectedRows ・・・Updateの対象になったレコード数
cahngedRows ・・・実際に値が更新されたレコード数
つまりはこういうことです

こんなテーブルがあったとして
table test
ID NAME
1 HOGE
2 FUGA
3 HOGE
4 FUGA これを実行すると
update test set NAME = 'FUGA'; affectedRows = 4
changedRows = 2 となります。

Streaming query rows

なんて訳せばよいの?
こんな書き方もできます。

var query = connection.query('SELECT * FROM posts');
query
.on('error', function(err) {
// Handle error, an 'end' event will be emitted after this as well
})
.on('fields', function(fields) {
// the field packets for the rows to follow
})
.on('result', function(row) {
// Pausing the connnection is useful if your processing involves I/O
//pause()を実行すると、以降resultイベントが発生しない
connection.pause(); processRow(row, function() {
connection.resume();
});
})
.on('end', function() {
// all rows have been received
});

複数の命令文を実行する場合

//コネクション作る際にmultipleStatementsにtrueをセット
var connection = mysql.createConnection({multipleStatements: true});
connection.query('SELECT 1; SELECT 2', function(err, results) {
if (err) throw err; // `results` is an array with one element for every statement in the query:
console.log(results[0]); // [{1: 1}]
console.log(results[1]); // [{2: 2}]
});

このようにresultsが配列で返ってくる
Streamで書くなら

var query = connection.query('SELECT 1; SELECT 2');

query
.on('fields', function(fields, index) {
// the fields for the result rows that follow
})
.on('result', function(row, index) {
// index refers to the statement this result belongs to (starts at 0)
});

ストアドプロシージャ。

 connection.query('call hoge()');

ここでも?が使えるのかな?試してない。

重複したフィールド名の解決

よくわからんけど、フィールド名が重複するような場合には、nestTablesを有効にしておくと、
テーブル名でネストして結果を返してくれるよ

var options = {sql: '...', nestTables: true};
connection.query(options, function(err, results) {
/* results will be an array like this now:
[{
table1: {
fieldA: '...',
fieldB: '...',
},
table2: {
fieldA: '...',
fieldB: '...',
},
}, ...]
*/
});

またはフィールド名にテーブル名をつけてマージすることもできるよ

var options = {sql: '...', nestTables: '_'};
connection.query(options, function(err, results) {
/* results will be an array like this now:
[{
table1_fieldA: '...',
table1_fieldB: '...',
table2_fieldA: '...',
table2_fieldB: '...',
}, ...]
*/
});

トランザクション

コネクションレベルで使えます

//トランザクション開始
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('INSERT INTO posts SET title=?', title, function(err, result) {
if (err) {
//insertに失敗したら戻す
connection.rollback(function() {
throw err;
});
} var log = 'Post ' + result.insertId + ' added'; connection.query('INSERT INTO log SET data=?', log, function(err, result) {
if (err) {
//insertに失敗したら戻す
connection.rollback(function() {
throw err;
});
}
//コミットする
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log('success!');
});
});
});
});

コネクションプール(Pooling connections)

var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'example.org',
user : 'bob',
password : 'secret'
}); pool.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err; console.log('The solution is: ', rows[0].solution);
});

シングルコネクションの場合

var mysql = require('mysql');
var pool = mysql.createPool({
host : 'example.org',
user : 'bob',
password : 'secret'
});

使っちゃってもリリースしてあげればプールに戻るよ

var mysql = require('mysql');
var pool = mysql.createPool(...); pool.getConnection(function(err, connection) {
// Use the connection
connection.query( 'SELECT something FROM sometable', function(err, rows) {
// プールに戻す
connection.release(); // ここでconnectionをつかっちゃだめだよ。すでにプールに返しちゃったからね。
});
});

もう使わないならdestroy

connection.destroy()

プールイベント

connection

コネクションが使われたゾ

pool.on('connection', function (connection) {
connection.query('SET SESSION auto_increment_increment=1')
});

enqueue

戻ってきたぞ

pool.on('enqueue', function () {
console.log('Waiting for available connection slot');
});
//endしたあとにpool.getConnectionとかしても、もう何もしてやんないから。

プールを閉園します。

pool.end(function (err) {
// all connections in the pool have ended
});

プールクラスター(PoolCluster)

プール(各コネクション)に名前を付けてあげましょうってことかな?

// create
var poolCluster = mysql.createPoolCluster(); // add configurations
poolCluster.add(config); // anonymous group
poolCluster.add('MASTER', masterConfig);
poolCluster.add('SLAVE1', slave1Config);
poolCluster.add('SLAVE2', slave2Config); // remove configurations
poolCluster.remove('SLAVE2'); // By nodeId
poolCluster.remove('SLAVE*'); // By target group : SLAVE1-2 // Target Group : ALL(anonymous, MASTER, SLAVE1-2), Selector : round-robin(default)
poolCluster.getConnection(function (err, connection) {}); // Target Group : MASTER, Selector : round-robin
poolCluster.getConnection('MASTER', function (err, connection) {}); // Target Group : SLAVE1-2, Selector : order
// If can't connect to SLAVE1, return SLAVE2. (remove SLAVE1 in the cluster)
poolCluster.on('remove', function (nodeId) {
console.log('REMOVED NODE : ' + nodeId); // nodeId = SLAVE1
}); poolCluster.getConnection('SLAVE*', 'ORDER', function (err, connection) {}); // of namespace : of(pattern, selector)
poolCluster.of('*').getConnection(function (err, connection) {}); var pool = poolCluster.of('SLAVE*', 'RANDOM');
pool.getConnection(function (err, connection) {});
pool.getConnection(function (err, connection) {}); // close all connections
poolCluster.end(function (err) {
// all connections in the pool cluster have ended
});

Ping

connection.ping(function (err) {
if (err) throw err;
console.log('Server responded to ping');
})

タイムアウト処理

// Kill query after 60s
connection.query({sql: 'SELECT COUNT(*) AS count FROM big_table', timeout: 60000}, function (err, rows) {
if (err && err.code === 'PROTOCOL_SEQUENCE_TIMEOUT') {
throw new Error('too long to count table rows!');
} if (err) {
throw err;
} console.log(rows[0].count + ' rows');
});

エラー処理

err.codeには下記の種類があります。
MySQL serverのエラー (たとえば 'ER_ACCESS_DENIED_ERROR')
node.jsのエラー (たとえば 'ECONNREFUSED')
内部エラー (たとえば 'PROTOCOL_CONNECTION_LOST')

var connection = require('mysql').createConnection({
port: 84943, // わざと間違ったポートを指定してみる
}); connection.connect(function(err) {
console.log(err.code); // 'ECONNREFUSED'
console.log(err.fatal); // true
}); connection.query('SELECT 1', function(err) {
console.log(err.code); // 'ECONNREFUSED'
console.log(err.fatal); // true
});

エラーはほかの処理には影響しない(含まれない)。
たとえば下記のような場合

//存在しないDBに接続
connection.query('USE name_of_db_that_does_not_exist', function(err, rows) {
console.log(err.code); // 'ER_BAD_DB_ERRORが発生'
});
//その後下記クエリを実行
connection.query('SELECT 1', function(err, rows) {
console.log(err); // null ここにエラーは含まれない
console.log(rows.length); // 1
});

こんな風にエラー処理することもできます。

connection.on('error', function(err) {
console.log(err.code); // 'ER_BAD_DB_ERROR'
}); connection.query('USE name_of_db_that_does_not_exist');

型変換(Type casting)

デフォルトで、JavaScriptの型に下記のように自動変換されます。
(一部未翻訳スミマセン)

Number型

TINYINT
SMALLINT
INT
MEDIUMINT
YEAR
FLOAT
DOUBLE

Date型

TIMESTAMP
DATE
DATETIME

Buffer型

TINYBLOB
MEDIUMBLOB
LONGBLOB
BLOB
BINARY
VARBINARY
BIT (last byte will be filled with 0 bits as necessary)

String型

Note text in the binary character set is returned as Buffer, rather than a string.

CHAR
VARCHAR
TINYTEXT
MEDIUMTEXT
LONGTEXT
TEXT
ENUM
SET
DECIMAL (may exceed float precision)
BIGINT (may exceed float precision)
TIME (could be mapped to Date, but what date would be set?)
GEOMETRY (never used those, get in touch if you do)
It is not recommended (and may go away / change in the future) to disable type casting, but you can currently do so on either the connection:

おすすめしないけど、型変換をoffにできます。

//コネクションレベルでoff
var connection = require('mysql').createConnection({typeCast: false}); //クエリレベルでoff
var options = {sql: '...', typeCast: false};
var query = connection.query(options, function(err, results) { });

また、自分で型変換を定義できます。

connection.query({
sql: '...',
typeCast: function (field, next) {
if (field.type == 'TINY' && field.length == 1) {
return (field.string() == '1'); // 1 = true, 0 = false
}
return next();
}
});

参考リンク

https://github.com/felixge/node-mysql

終わり

Node.jsでMySQLを使うメモ的更多相关文章

  1. Node.js + MySQL 实现数据的增删改查

    通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...

  2. 零代码第一步,做个添加数据的服务先。node.js + mysql

    node.js + mysql 实现数据添加的功能.万事基于服务! 增删改查之添加数据. 优点:只需要设置一个json文件,就可以实现基本的添加功能,可以视为是零代码. 添加数据的服务实现的功能: 1 ...

  3. node.js+mysql环境搭建

    https://www.jianshu.com/p/9b338095cbe8 node.js+mysql环境搭建 0x01 前言 随着html web技术的发展,和全栈式开发的需求,对于前端人员来讲, ...

  4. Ubuntu 16.04 下部署Node.js+MySQL微信小程序商城

    转载于这篇文章 关于pm2看这篇文章 最近在研究小程序,申请了域名之后,再一次来配置环境,根据作者的步骤基本上完成了网站的架构,但由于环境路径等不同,配置上会有所不同,因此记录下来. 1.更新系统和安 ...

  5. Node.JS + Mysql数据库

    服务嘛,当然离不开数据库了,你要是见到数据就哭了,我建议你还是看看本文,不要做数据哭啊,哈哈哈 要做 ‘数据酷’嘛,哈哈哈 一 安装 1. wget -i -c http://dev.mysql.co ...

  6. node.js+mysql用户的注册登录验证

    下面代码实现的功能是:用node.js连接mysql实现用户的注册和登录,这里主要实现的是后端的验证代码,前端显示部分没具体写出. 整个程序的流程是这样的: 1.首先建立数据库reji,数据表user ...

  7. Node.js实操练习(一)之Node.js+MySQL+RESTful

    前言 最近学习了一下node.js相关的内容,在这里初步做个小总结,说实话关于本篇博客的相关内容,自己很久之前就已经有过学习,但是你懂的,“好记性不如烂笔筒”,学过的东西不做笔记的话,很容易就会忘记的 ...

  8. node.js+mysql把数据显示到前端简单实例

    原以为数据查出来了,要展示是鸡毛蒜皮的事儿!谁知道,我弄了一天....我错就错在没把connection.query里面. 下面的例子是可以的了! 看过我之前文章的同学,应该很熟悉下面的代码,对!主要 ...

  9. 借助node.js + mysql 学习基础ajax~

    很多小白不知道ajax怎么学,所以就弄了个node后台模拟下基本的ajax请求. 环境要求是安装node~ 先上linkMysql.js var mysql = require('mysql') va ...

随机推荐

  1. Internet Explorer 10 administration IE10管理

    http://4sysops.com/archives/internet-explorer-10-administration-part-1-overview/ http://4sysops.com/ ...

  2. 【转】在单片机中,C语言的一些误用和总结!

    在学习单片机的时候才真正知道C语言是什么,它是来干什么的~但是C语言用到嵌入式只是它小小的一部分应用,还有很多地方呢. 我们是不是在写程序的时候,错误很多就算编译通过了也达不到我们预期的结果,完了自己 ...

  3. Luogu 2540 斗地主增强版(搜索,动态规划)

    Luogu 2540 斗地主增强版(搜索,动态规划) Description 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游 ...

  4. 【CH5105】cookies 贪心+DP

    通过邻项交换法可知,怨气值大的孩子分得的饼干数也应该多(否则交换之后得到的解更优). 观察目标函数的性质,可知目标函数本身是由孩子饼干数的相对大小得到,因此此题中关注的是相对大小. 状态设计:\(dp ...

  5. 获取EasyUI的treegrid的checkbox所有已勾选的数据

    EasyUI为TreeGrid的已勾选节点,未勾选节点,只勾选部分子节点的父节点分别添加了三个不同的样式,如下:样式一:tree-checkbox2 有子节点被选中样式二:tree-checkbox1 ...

  6. MYCAT扩容

    一.原架构图: 二.扩容 在HOST1上新增节点db_user2 在HOST2上新增节点db_user2 三.操作步骤 1.mycat 所在环境安装 mysql 客户端程序 2.mycat 的 lib ...

  7. 在tomcat集群下利用redis实现单点登陆

    场景:比如说我们要实现一个集群环境,无非是把多个项目部署到多个tomcat下,然后按照一定的算法,轮询什么的随机访问多个tomcat服务器,但是问题也会有许多,比如说,我们最开始是把登陆人的信息存放到 ...

  8. HDU - 3478 Catch(判奇环/二分图)

    http://acm.hdu.edu.cn/showproblem.php?pid=3478 题意 给一个无向图和小偷的起点,小偷每秒可以向相邻的点出发,问有没有一个时间点小偷可能出现在任何点. 分析 ...

  9. Java编程思想 学习笔记12

    十二.通过异常处理错误  Java的基本理念是“结构不佳的代码不能运行”. Java中的异常处理的目的在于通过使用少于目前数量的代码来简化大型.可靠的程序的生成,并且通过这种方式可以使你更加自信:你的 ...

  10. JMS学习(七)-ActiveMQ消息的持久存储方式之KahaDB存储

    一,介绍 自ActiveMQ5.4以来,KahaDB成为了ActiveMQ默认的持久化存储方式.相比于原来的AMQ存储方式,官方宣称KahaDB使用了更少的文件描述符,并且提供了更快的存储恢复机制. ...