node-mysql文档翻译

模块Github地址

安装

npm install mysql

如果需要以前的版本0.9.x系列的文档,请访问v0.9 branch.
有时你可以从github中安装最新版本的node-mysql,具体怎么做请参考下面的示例:

npm install felixge/node-mysql

介绍

这是一个node.Js的mysql驱动程序。这个驱动完全是用javascript写的,不需要任何编译工作。完全的遵守MIT开源协议。
这里有一个简单的示例告诉你如何使用它:

var mysql = require('mysql');
var connection = mysql.createConnection({
  host : 'localhost',
  user : 'me',
  password : 'secret'
});

connection.connect(); //建立连接
connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
  if (err) throw err;
  console.log('The solution is: ', rows[0].solution);
});

connection.end(); //释放连接

从上面这个例子中,你应该要知道如下的两点:

  1. 每个方法调用在连接队列中是按顺序执行。
  2. 当使用 end() 函数关闭连接时候,你必须要确保你的所有查询都已经发送给了mysql服务器。否者end()之后的查询是无效的。

创建连接

推荐的一种连接方式:

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

connection.connect(function(err) {
// 成功连接! (unless err is set)
});

然而,一个连接只能隐式的调用一个query函数。调用方式如下:

var mysql = require('mysql');
var connection = mysql.createConnection(...);

connection.query('SELECT 1', function(err, rows) {
// 成功连接! (unless err is set)
});

上面的两种错误处理方法都合适,这取决于你更喜欢那一种方式来做数据库错误信息处理。任何一种连接上的错误(握手与网络)都会被视为致命错误,具体更多的错误处理信息可以查看Error Handling章节。

连接可选参数

当我们使用Node-MySQL建立一个数据库连接的时候你可以通过下面这些选项:

参数名 代表值
host 数据库的主机名(默认: localhost
port 数据库服务器的端口(默认: 3306)
localAddress 使用TCP连接的源IP地址(可选)
socketPath 使用Unix域套接字连接的路径,当使用 host 与 port 的时候可以忽略。
user 这个是MySQL身份验证的用户名。
password MySQL用户的密码。
database 连接的数据库名(可选).
charset 连接之后的字符编码(默认:' UTF8_GENERAL_CI',值得提醒的是,这个值必须都是大写字母).
timezone 这个是储存数据的是当前时间。(默认:local).
connectTimeout MySQL初始连接的超时时间。单位是毫秒(默认:无超时限制)。
stringifyObjects 把值转换为 Stringify 对象。(默认:false)。
insecureAuth 允许使用老(不安全)的身份认证方式去连接MySQL数据库.(默认: false).
typeCast 是否把结果值转换为原生的 javascript 类型(默认: true).
queryFormat 一个可以自己定义查询格式函数(具体见Custom format)。
supportBigNumbers 当在数据库中处理一个大数(BIGINT和DECIMAL)数据类型的时候,你需要启用这个选项(默认: false).
dateStrings 强制为date类型(TIMESTAMP,DATETIME,DATE)转化为一个字符串返回而不是转换成 javascript的date类型对象。(默认: false)
debug 答应协议详细信息到标准输出(默认: false).
trace 产生栈跟踪当在库的入口点出现error时,当调用数次很多时性能会略微下降(默认: true).
multipleStatements 允许每个mysql语句有多条查询.使用它时要非常注意,因为它很容易引起sql注入攻击(默认:false).
flags 使用连接标示符号标示出超过默认的值的连接。它也可以加到默认的黑名单连接中。更多信息参考(Connection Flags)。
ssl 使用ssl参数对象(格式参考crypto.createCredentials参数)或者是用一个包含ssl配置的字符串名。目前仅仅支持亚马逊的ca证书,参考:https://rds.amazonaws.com/doc/rds-ssl-ca-cert.pem
bigNumberStrings 这个选项需要bigNumberStrings与 supportBigNumbers同时启用,强制把数据库中大数(BIGINT和DECIMAL)数据类型的值转换为javascript字符对象串对象返回。(默认:false)。当启用supportBigNumbers选项,但 bigNumberStrings是未启用的状态。当无法用javascript数字对象(JavaScript Number objects)所表达的时候就会返回的是一个big number字符串对象(值的范围要在 [-253, +253]之间).否则将会返回一个Number类型的对象。如果supportBigNumbers是false那么这个选项会被自动忽略。

除了利用这些选项来做对象使用,你也可以用一个字符串来标示。例如:

var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI&timezone=-0700');

注意:查询出来的值第一会尝试转换为json格式,如果转换失败.那么就会转换成纯文本的字符串.

关闭连接

有两种关闭连接的方式,当查询完成后最优雅关闭连接方式是调用end()方法,例如:

connection.end(function(err) {
// 连接在这里会被终止
});

这样可以确保在查询队列完成之后发送一个 COM_QUIT 包到mysql服务器。如果在发送 COM_QUIT 出现致命的错误。在回调函数里面有一个err参数可以使用。但是这个连接无论如何也会被关闭掉。

另外一种替代end()方法的是调用destroy()方法,这个方法会立即终止底层socket连接.destroy()方法确保了没有任何事件或回调再连接触发。

connection.destroy();

destroy()方法不像end()方法, destroy()方法是没有任何回调参数的。

连接池

直接使用连接池

var mysql = require('mysql');
var pool = mysql.createPool({
  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'
});
pool.getConnection(function(err, connection) {
// 连接成功! (除非有err )
});

如果你想在连接前设置session变量并且获取使用。你可以监听connection事件:

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

当你的连接完成后,只需要调用connection.release()方法。将连接返回到池中,以供其他人再次使用。

var mysql = require('mysql');
var pool = mysql.createPool(...);
pool.getConnection(function(err, connection) {
  // 使用连接
connection.query( 'SELECT something FROM sometable', function(err, rows) {
  // 连接使用完成后释放连接
  connection.release();
    // 不要在这里使用connection进行查询,因为连接已经被归还到连接池了
  });
});

如果你想关闭连接并且从连接池中移除,使用connection.destory()方法代替。当你下一次需要使用的时候,池会自动创建一个新的连接。
通过池创建连接是非常缓慢的。如果你配置你的连接池最大的连接数为100,当你只需要同时使用5个连接时候,它也仅仅只会创建5个连接。这种连接的循环方式是一种轮询(round-robin)的方式。采取的是从连接池顶部到底部的方式。

Pool参数选项

池连可以接受一些连接的参数选项。当一个连接创建之后,这些参数选项通过简单的构造传递到连接里面。池连接参数可以接受下面这些参数。waitForConnections:判断当前的连接是否可用并且是否已经达到了连接数的上限。如果是true。这个连接就会加入到连接队列中同时把状态转换为可用状态。如果是false,那么会立即返回一个错误给开发者。(默认:true).connectionLimit:一次连接最大的连接数(默认:10)。queueLimit:从getConnection获取连接数并且判断是否超出了queneLimit限制的排队等待的连接值,如果是就返回一个错误。如果设置为0,就是不限制连队列数(默认:0)。

PoolCluster

PoolCluster提供了多台主机连接功能(group&retry&selector):

// 创建连接
var poolCluster = mysql.createPoolCluster();
poolCluster.add(config); // anonymous group
poolCluster.add('MASTER', masterConfig);
poolCluster.add('SLAVE1', slave1Config);
poolCluster.add('SLAVE2', slave2Config);

// 目标主机组 : ALL(anonymous, MASTER, SLAVE1-2), 连接方式 : round-robin(default)
poolCluster.getConnection(function (err, connection) {});

// 目标主机组 : MASTER, 连接方式: round-robin
poolCluster.getConnection('MASTER', function (err, connection) {});

// 目标主机组 : SLAVE1-2, 连接方式 : order
// 如果不能连接到SLAVE1就连接SLAVE2(把SLAVE1从集群节点中删除)
poolCluster.on('remove', function (nodeId) {
  console.log('REMOVED NODE : ' + nodeId); // 节点ID= SLAVE1 
});

poolCluster.getConnection('SLAVE*', 'ORDER', function (err, connection) {
});

// 命名方式: 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) {
});

// 释放连接
poolCluster.end();

PoolCluster选项

参数名 代表值
canRetry 如果是true,当连接失败时Poolcluster会尝试重新连接(默认:true)。
removeNodeErrorCount 如果连接失败,节点的errorCount将会增加.当errorCount大于removeNodeErrorCount时,会从poolCluster中移除一个节点。(默认:5).
defaultSelector 默认选择器(默认:RR).
RR 选择一个交替(轮循)
RANDOM 由随机函数选择一个节点.
ORDER 按照顺序无条件的选择第一个节点。
var clusterConfig = {
  removeNodeErrorCount: 1, // 连接失败后立即从把该节点移除
  defaultSelector: 'ORDER'
};

var poolCluster = mysql.createPoolCluster(clusterConfig);

切换用户/修改连接状态

MySQL提供了ChangeUser的命令,允许你更改当前用户并且切换用户时不需要关闭底层socket连接:

connection.changeUser({user : 'john'}, function(err) {
  if (err) throw err;
});

这个功能提供了几个有用的参数选项:

参数名 代表值
user 新用户的名字。(默认为切换新用户前第一个用户)
password 新用户的密码(默认为切换新用户前第一个用户)
charset 新的字符编码(默认为切换新用户前第一个用户)
database 新的数据库名(默认为切换新用户前第一个用户)

这个功能有时有一个副作用,它会把所有的连接状态都重置(变量,事务).
注意:此操作出现的错误会被该模块视为致命错误处理。

服务器连接断开

由于网络问题你有可能丢失与MySQL服务器的连接。也有可能被服务器踢出连接,还有可能是服务器重启或是崩溃等等,这些都是致命的错误都被归为error对象里面。并且模块提供了err.code = 'PROTOCOL_CONNECTION_LOST'信息,更多的错误处理信息请参考Error Handling 。
与服务器重连是建立一个新的连接,一旦现在的连接断开就不能让这个连接重新连接。它必须重新建立一条连接,连接到数据库服务器。
在连接池里面,当连接断开时会从连接池里面把连接移除,当下次需要连接的时候调用getConnection创建一个新的连接。

转义查询值

为了避免被SQL注入攻击,你需要把用户提交过来的数据进行转义之后再放到SQL查询语句里面。模块提供了connection.escape()和Pool.escape()两种方法:

var userId = 'some user provided value';
var sql = 'SELECT * FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function(err, results) {
  // ...
});

或者,你可以使用占位符'?'来代替,同样的也能对传入的值进行转义:

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

这看起来像是使用了MySQL的预处理语句,其实同样的在MySQL内部也是使用了类似connection.escape()的方法。
不同的是类型转义的值不同。请看下面的解释:

  1. Number类型保存不变.
  2. Boolean值被转换为了true/false字符串.
  3. Date类型被转换为了'YYYY-mm-dd HH:ii:ss'字符串
  4. Buffer转换为了16进制,例如:X'0fa5'
  5. String转换为了安全的字符串。
  6. Array转换为了list。例如:['a','b']会返回'a','b'
  7. 多维数组会被转换为多维list。例如[['a', 'b'], ['c', 'd']]返回('a', 'b'), ('c', 'd')
  8. Object转换为key = 'val';多维Object对象会转换为字符串.
  9. undefined/null会转换为null
  10. NaN / Infinity 保持不变,因为MySQL现在并不支持这些对象,如果你把NaN/Infinity做为值,MySQL会报错.直到它们被MySQL支持。

如果你留意了,你会发现转义查询值可以巧妙的用下面这种方式:

var post = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
  // 非常完美!
});
console.log(query.sql); // INSERT INTO posts SET id = 1, title = 'Hello MySQL'

如果你觉得有必要自己去转义查询值,那么你可以直接去调用转义函数:

var query = "SELECT * FROM posts WHERE title=" + mysql.escape("Hello MySQL");
console.log(query); // SELECT * FROM posts WHERE title='Hello MySQL'

转义查询标示符
如果你不信任用户提交过来的标示符((database / table / column name))。那么你需要使用mysql.escapeId(identifier)来转义:

var sorter = 'date';
var query = 'SELECT * FROM posts ORDER BY ' + mysql.escapeId(sorter);
console.log(query); // SELECT * FROM posts ORDER BY date

它还支持添加合格的转义符。不过得把转义的分成两部分:

var sorter = 'date';
var query = 'SELECT * FROM posts ORDER BY ' + mysql.escapeId('posts.' + sorter);
console.log(query); // SELECT * FROM posts ORDER BY posts.date

或者,你可以使用占位符'??',它会自动转义查询的值:

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

请注意:最后的一个字符转义目前还在实验阶段,而且语法随时可能发生改变。

当你使用.escape(),.query(),.escapeId()时可以有效的防御SQL注入攻击.

预查询

你可以使用mysql.format()去执行预处理多嵌套查询语句,利用适当的转义处理对于标示符与值.下面有一个简单的例子:

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

这种方法可以确保发送到数据库进行数据查询之前就能够保证查询语句的安全,在发送到数据库查询之前执行预查询,这个功能非常的有用。
由于mysql.format是由sql的String.format暴露出来的。所以你可以你还可以选择传递stringifyObject 和timezone对象(不强制要求)。
并且允许您自定义把对象转换字符串的方法。以及特定地区的时间和时区(location specific/timezone aware Date).

自定义格式

如果您喜欢其他样式的转义格式。你可以在连接配置选项中自定义你的功能函数。如果你还想使用escape()或其他内置的函数。可以直接调用
这儿我们提供了一个示例:

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

如果你想获取插入一行值之后,获取自动递增主键的ID。你可以这样获取:

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

当处理大数字的时候(超过javascriptNumber类型的精度),你需要启用supportBigNumbers以便把ID作为字符串类型读取。否者会抛出错误.
而且当从数据库中查询的数字是一个big number类型的时候,你也需要把supportBigNumbers选项设置为true,否则查询出来的数据在传输过来的时候由于精度限制,自动删除超出部分。

执行并行查询

MySQL的协议是顺序执行的。所以这就意味这你需要建立多个连接去实现并行查询,你应该需要一个池(Pool)来管理连接。一个简单的方法就是每一个连接都创建的一个HTTP请求连接.

数据流查询

有时,你可能去执行一个大的查询,并且要处理查询返回的每一行结果。那么你可以尝试这样做:

var query = connection.query('SELECT * FROM posts');
query.on('error', function(err) {
  // 处理错误,当出现错误时,会立即发出一个end事件
  }).on('fields', function(fields) {
    // the field packets for the rows to follow
  }).on('result', function(row) {
    // 处理工程中涉及到I/O可以在这里先暂停连接
    connection.pause();
    processRow(row, function() {
    connection.resume();
    });
  }).on('end', function() {
    // 获取所有查询内容
  });

在上面的例子中请注意几件事情:

  1. 同常的时候你希望当接收到一定数量的查询结果的时候再执行pause()方法,这数量取决于你查询总的数量和数据的大小。
  2. pause()/resume()操作底层socket和解析器时,可以确定在调用pause()方法之后再有result事件被执行。
  3. 当有多条数据流读取时,不能再给query()方法添加一个回调函数。
  4. 在'result'事件中不仅可以返回查询的数据也可以确认query/INSERT执行是否成功。
  5. 除此之外,你应该有兴趣知道当前的模块并不支持单独一行的流读取。它们都是被缓存起来当SQL执行完之后一并把结果返回过来。假如你有在大型的案例中应用到了MySQL的流技术。我很想能够与您分享。

管道结果(Piping results)和Streams2

query对象提供了一个非常方便的方法.stream(可选).它把查询事件封装成了可读(Readable)的Streams2对象,此流可以很容易地通过管道downstream,并提供自动化暂停/恢复,基于downstream堵塞和可选highWaterMark。该流的objectMode参数默认设为true 。

例如,把查询结果通过piping导入到另一个流中(最大缓存为5)的简单例子:

connection.query('SELECT * FROM posts')
.stream({highWaterMark: 5})
.pipe(...);

多语句查询

出于安全考虑,多语句查询默认是禁用的.(如果值没有经过转义,那么很有可能会导致SQL注入攻击)。如果你想使用此功能,你必须在连接中启用它:

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}]
});

此外,您也可以串行理的多个语句查询的结果:

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)
});

如果你有一个查询语句出现了错误,那么抛出的错误会包含在err.index属性里面并且会告诉你是哪条语句出现了错误。同时当发生错误时对于剩余的查询语句MySQL也会停止执行.

注意:目前利用流来执行多条查询语句的接口还在试验阶段。所以我很期待能够得到您的反馈。

储存过程

你可以在你的查询语句里面调用MySQL驱动中自带的任何存储过程,如果你使用存储过程生成的多个结果集,其实也就与您使用多语句查询生成得出的结果是一样的。

合并重叠的字段

当我们使用JOIN函数执行查询的时候得到的结果里面有很多字段是重复的。默认情况下Node-MySQL会按照列读取顺序把一些冲突的列名进行合并。但是这样有可能会导致一些接收到的值变得不可用。
不过,您可以指定在表名中嵌套您需要的列,就像这样:

var options = {sql: '...', nestTables: true};
connection.query(options, function(err, results) {
  /* 结果将会像下面这样的数组形式返回: 
  [{
  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) { 
      connection.rollback(function() {
        throw err;
      });
    }
    
    var log = 'Post ' + result.insertId + ' added';
    connection.query('INSERT INTO log SET data=?', log, function(err, result) {
      if (err) { 
        connection.rollback(function() {
          throw err;
        });
      }
    
      connection.commit(function(err) {
        if (err) { 
          connection.rollback(function() {
            throw err;
          });
        }
        console.log('success!');
      });
    });
  });
});

请注意,执行START TRANSACTION, COMMIT,和 ROLLBACK 这些简单命令的方法分别是transaction(),Commit()和rollback(),了解MySQL中一些会造成隐式提交语句很重要。

错误处理

这个模块包含了错误处理机制,不过在编码的时候你还应该去自己检查自己的代码。看看是否会有一些意想不到的错误。
这个模块中所有的错误都是javascript error的对象实例,同时它还有两个属性:

  1. err.code: 任一的MySQL错误 MySQL server error (例如. 'ER_ACCESS_DENIED_ERROR'), Node.js错误 (例如.'ECONNREFUSED') 或者是内部错误 (e.g. 'PROTOCOL_CONNECTION_LOST').

  2. err.fatal:布尔值,这个对象表示是否能够连接到服务器.

致命的错误都可以在回调函数中捕获到。在下面这个例子中,所引起的错误是因为改连接试图连接到一个无效的端口上面。因此错误对象会被传递到回调函数中并且能够使用err.code或err.fatal知道错误的具体情况:

var connection = require('mysql').createConnection({
  port: 84943, // WRONG PORT
});

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
});

一般情况下错误是只委托给它所属的回调函数,例如下面这个例子。只有第一个回调函数接收到了错误信息,而第二个同样是按照预期的方式执行的并不会捕获第一个查询的错误:

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');

注意:error在Node中是一个特殊的对象,如果它没有被挂在一个事件上而是单独出现,那么就很有可能出现堆栈错误并且关闭NodeJS程序进程.
最后:这个模块处理错误的初衷都不是悄悄的处理掉错误,你应该把错误的处理放在回调函数里面。但是如果你不喜欢这么麻烦并且忽略掉错误。那么你可以这样做:

// I am Chuck Norris:
connection.on('error',function(){
  //...
});

异常安全处理

这个模块的异常处理很安全,也就是说在回调函数中抛出一个错误之后你可以使用’uncaughtException‘或域(domain)去捕获错误,然后继续的去使用做下面的事情。

类型转换

为了您的使用方面,这个驱动会自动把MySQL中的一些类型转换为原生的javascript的类型。下面列举的是转换的类型:
Number:

  • TINYINT
  • SMALLINT
  • INT
  • MEDIUMINT
  • YEAR
  • FLOAT
  • DOUBLE

Date:

  • TIMESTAMP
  • DATE
  • DATETIME

Buffer:

  • TINYBLOB
  • MEDIUMBLOB
  • LONGBLOB
  • BLOB
  • BINARY
  • VARBINARY
  • BIT (最后一个字节会使用0来填充)

String:

  • CHAR
  • VARCHAR
  • TINYTEXT
  • MEDIUMTEXT
  • LONGTEXT
  • TEXT
  • ENUM
  • SET
  • DECIMAL (可能会超过float精度)
  • BIGINT (可能会超过float精度)
  • TIME (转换为日期, but what date would be set?)
  • GEOMETRY (从来没有用错,当你使用的时候你可以联系我们)

我们不建议你把类型转换这个参数禁用,但是如果你想禁用也可以在连接的时候就去做(这种方法可能在以后的版本中删除/改变):

var connection = require('mysql').createConnection({typeCast:false});

或者在查询层做:

var options = {sql: '...', typeCast: false};
var query = connection.query(options, function(err, results) {

});

你也可以通过一个处理函数来转换自己想要的类型,通过已知的一些字段的信息,像数据库,表名和字段名,数据类型和长度。如果你只想自己定义一个类型转换函数。你可以在查询的回调函数中做。例如你把TINYINT(1)转换为布尔值:

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

警告:你必须使用解析器中内建的三个field函数中的一个,在你自定义的类型转换回调函数中。他们只能调用一次:

field.string()
field.buffer()
field.geometry()
//或者使用别名:
parser.parseLengthCodedString()
parser.parseLengthCodedBuffer()
parser.parseGeometryValue()

如果你需要使用field函数,。你可以在RowDataPacket.prototype._typeCast中找到关于field函数的一些文档资料

连接标记

如果,由于某些原因你需要修改默认的连接标记,那么你可能需要使用flags选项。通过在连接配置的选项列表中添加这个选项,那么你就可以修改默认的连接标记.如果你不想使用默认的flag你可以使用一个减号来取消掉。或者在连接的配置选项列表里面添加一个flag选项,而不写值,仅仅就是一个flag名字在哪里(不区分大小写)。
PS:不想像去掉flag选项一样在flag的前面加一个+号:

请注意:有些默认的flag目前还不支持(例如:SSL,Compression)。

例子:
下面的例子是使用黑名单FOUND_ROWS flag例子:

var connection = mysql.createConnection("mysql://localhost/test?flags=-FOUND_ROWS");

默认标记:

  • LONG_PASSWORD
  • FOUND_ROWS
  • LONG_FLAG
  • CONNECT_WITH_DB
  • ODBC
  • LOCAL_FILES
  • IGNORE_SPACE
  • PROTOCOL_41
  • IGNORE_SIGPIPE
  • TRANSACTIONS
  • RESERVED
  • SECURE_CONNECTION
  • MULTI_RESULTS
  • MULTI_STATEMENTS (如果使用 multipleStatements 选项就激活)

其他的可用标记:

  • NO_SCHEMA
  • COMPRESS
  • INTERACTIVE
  • SSL
  • PS_MULTI_RESULTS
  • PLUGIN_AUTH
  • SSL_VERIFY_SERVER_CERT
  • REMEMBER_OPTIONS

调试与问题查看

如果在运行过程中出现了问题,你可以在连接的配置选项中添加一个debug参数来帮助你调试:

var connection = mysql.createConnection({debug: true});

它会将输入的信息与输出的信息标准输出的显示出来,你还可以通过把数据包的类型转换成一个数据数组对象来方便调试:

var connection = mysql.createConnection({debug: ['ComQueryPacket', 'RowDataPacket']});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容