這基於是node-mysql官方文檔的部分中文翻譯,由於最近要在nodejs上使用mysql,看文檔的時候順帶把這個文檔部分翻譯了,無責任翻譯,不齊全也可能有些地方不對,不好勿噴。
node-mysql 項目地址
我的博客
安裝穩定版本:
$ npm install mysql
安裝最新版本:
$ npm install felixge/node-mysql
這是一個用Javascript編寫的Node.js鏈接Mysql數據庫的驅動模塊。
建立連接的一種推薦方法:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'example.org',
user : 'bob',
password : 'secret'
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
然而,連接可以在查詢中隱式地建立:
var mysql = require('mysql');
var connection = mysql.createConnection(...);
connection.query('SELECT 1', function(err, rows) {
// connected! (unless `err` is set)
});
在建立一個連接時,可以使用以下選項:
host:主機地址 (默認:localhost)
user:用戶名
password:密碼
port:端口號 (默認:3306)
database:數據庫名
charset:連接字符集(默認:’UTF8_GENERAL_CI’,注意字符集的字母都要大寫)
localAddress:此IP用於TCP連接(可選)
socketPath:連接到unix域路徑,當使用 host 和 port 時會被忽略
timezone:時區(默認:’local’)
connectTimeout:連接超時(默認:不限制;單位:毫秒)
stringifyObjects:是否序列化對象(默認:’false’ ;與安全相關https://github.com/felixge/node-mysql/issues/501)
typeCast:是否將列值轉化為本地JavaScript類型值 (默認:true)
queryFormat:自定義query語句格式化方法 https://github.com/felixge/node-mysql#custom-format
supportBigNumbers:數據庫支持bigint或decimal類型列時,需要設此option為true (默認:false)
bigNumberStrings:supportBigNumbers和bigNumberStrings啟用 強制bigint或decimal列以JavaScript字符串類型返回(默認:false)
dateStrings:強制timestamp,datetime,data類型以字符串類型返回,而不是JavaScript Date類型(默認:false)
debug:開啟調試(默認:false)
multipleStatements:是否許一個query中有多個MySQL語句 (默認:false)
flags:用於修改連接標志,更多詳情:https://github.com/felixge/node-mysql#connection-flags
ssl:使用ssl參數(與crypto.createCredenitals參數格式一至)或一個包含ssl配置文件名稱的字符串,目前只捆綁Amazon RDS的配置文件
其它:
可以使用URL形式的加接字符串,不多介紹了,不太喜歡那種格式,覺得可讀性差,也易出錯,想了解的可以去主頁上看。
可以通過兩種方式關閉數據庫連接。
通過 end() 方法按照正常狀態關閉已經完成的數據庫連接:
connection.end(function(err) {
// The connection is terminated now
});
另外一種可選的方法是通過 destroy() 方法
這種方法會即刻執行,不管queries是否完成!
connection.destroy();
與 end() 不同的是, destroy() 方法不接受callback
建立一個查詢的最基本的方法是在一個連接實例(像Connection, Pool, PoolNamespace 或其他相似的對象)上調用 .query() 方法
query() 最簡單的形式是 .query(sqlString, callback), 第一個參數是SQL語句,第二個參數是回調函數:
connection.query('SELECT * FROM `books` WHERE `author` = "David"', function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
});
第二種形式 .query(sqlString, values, callback) 使用了占位符:
connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
});
第三種形式 .query(options, callback) 是在查詢中使用多種選項參數, 如 escaping query values,joins with overlapping column names,timeouts, 和type casting:
connection.query({
sql: 'SELECT * FROM `books` WHERE `author` = ?',
timeout: 40000, // 40s
values: ['David']
}, function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
});
注意當占位符作為參數傳遞而不是對象時,第二跟第三種形式可以結合來使用。
values 參數會覆蓋掉選項對象中的 values
connection.query({
sql: 'SELECT * FROM `books` WHERE `author` = ?',
timeout: 40000, // 40s
},
['David'],
function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
}
);
為了防止SQL注入, 你在對用戶提供的數據插入查詢語句前應該總是對其進行編碼 。
你可以這樣做:
mysql.escape(), 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) {
// ...
});
這裡本質上其實使用了同樣的 connection.escape() 方法
如果你留意的話, 你可能會注意到這可以使得你的語句變得簡潔:
var post = {id: 1, title: 'Hello MySQL'};
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
// Neat!
});
console.log(query.sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
如果你想自己進行編碼,你也可以直接使用 escaping 函數:
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),
connection.escapeId(identifier) 或pool.escapeId(identifier) 對其進行編碼:
var sorter = 'date';
var sql = 'SELECT * FROM posts ORDER BY ' + connection.escapeId(sorter);
connection.query(sql, function(err, results) {
// ...
});
也可以加入合適的標識符,這都會編碼.
var sorter = 'date';
var sql = 'SELECT * FROM posts ORDER BY ' + connection.escapeId('posts.' + sorter);
connection.query(sql, function(err, results) {
// ...
});
此外, 你可以使用 ?? 字符 作為占位符給你想要編碼的標志符如下:
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() or .query(), .escapeId() 來避免SQL注入。
你可以使用 mysql.format 來創建一個多插入點的查詢語句,對id和值適當的編碼 。一個簡單的例子:
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);
});
當處理大數字(在JavaScript數精度上),你應該考慮啟用supportbignumbers選項把ID作為字符串讀取插入,否則將會拋出錯誤。
在從數據庫取大數時也要啟用這個選項
你可以獲得從插入,更新或刪除語句受影響的行數。
connection.query('DELETE FROM posts WHERE title = "wrong"', function (err, result) {
if (err) throw err;
console.log('deleted ' + result.affectedRows + ' rows');
})
你可以獲得更新語句被改變的行數。
“changedRows”不同於 “affectedRows” 在於他不算沒有被改變的值
connection.query('UPDATE posts SET ...', function (err, result) {
if (err) throw err;
console.log('changed ' + result.changedRows + ' rows');
})
你可以使用threadId屬性獲取MySQL連接ID(“thread ID”)。
connection.connect(function(err) {
if (err) throw err;
console.log('connected as id ' + connection.threadId);
});
由於安全原因,默認是關閉的.
如果要用需要這樣創建連接:
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)
});
如果你的一個查詢語句導致錯誤,由此產生 Error
err.index 屬性就是你第幾條語句出錯
當發生錯誤時MySQL也將停止執行其余的語句。
該模塊自帶了錯誤處理,為了寫出健壯的應用,你應該仔細看。
通過本模塊創建的所有錯誤是JavaScript的Error對象實例
。他們有兩個屬性:
Error: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error
MySQL server error: http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
致命錯誤會掛起所有的回調。在下面的例子中,試圖連接到一個無效端口時觸發致命的錯誤。因此,錯誤傳遞到回調:
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
});
如果一個致命的錯誤產生,沒有一個待定的回調,或者當一個正常的錯誤產生而沒有屬於他的回調,錯誤會向連接對象發出error事件。下面的例子說明:
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中很特殊。如果他們出現而沒有綁定偵聽器,會打印堆棧跟蹤並且殺死你的進程。