nodejs與mysql資料庫的互動操作
首先通過npm命令安裝mysql模組
mysql資料庫版本:mysql-5.7.16-winx64,在官網下載zip包,修改一下配置,即可通過命令安裝到電腦上。
如何連線
連線流程程式碼如下:
var mysql = require('mysql'); //呼叫MySQL模組
//建立一個connection
var connection = mysql.createConnection({
host : '127.0.0.1', //主機
user : 'root', //MySQL認證使用者名稱
password:'12345' ,
port: '3306',
database: 'node'
});
//建立一個connection
connection.connect(function(err){
if(err){
console.log('[query] - :'+err);
return;
}
console.log('[connection connect] succeed!');
});
//執行SQL語句
connection.query('SELECT 1 + 1 AS solution', function (err, rows, fields) {
if (err) {
console.log('[query] - :'+err);
return;
}
console.log('The solution is: ', rows[0].solution);
});
//關閉connection
connection.end(function(err){
if(err){
return;
}
console.log('[connection end] succeed!');
});
關於Connection Optionos
要想建立一個數據庫連線,先就要認識清楚Options
host:主機地址 (預設:localhost)
user:使用者名稱
password:密碼
port:埠號 (預設:3306)
database:資料庫名
charset:連線字符集(預設:’UTF8_GENERAL_CI’,注意字符集的字母都要大寫)
localAddress:此IP用於TCP連線(可選)
socketPath:連線到unix域路徑,當使用 host 和 port 時會被忽略
timezone:時區(預設:’local’)
connectTimeout:連線超時(預設:不限制;單位:毫秒)
typeCast:是否將列值轉化為本地JavaScript型別值 (預設:true)
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)
ssl:使用ssl引數(與crypto.createCredenitals引數格式一至)或一個包含ssl配置檔名稱的字串,目前只捆綁Amazon RDS的配置檔案
其它:
可以使用URL形式的加接字串,不多介紹了,不太喜歡那種格式,覺得可讀性差,也易出錯,想了解的可以去主頁上看。
MYSQL CURD操作
增加
var mysql = require('mysql');
var DATABASE = "seckill";
var TABLE="seckill"
var connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'12345',
port:'3306',
database: DATABASE
});
connection.connect();
var addVip = 'insert into seckill(name,number) values(?,?)';
var param = ['100元秒殺家教機',100];
connection.query(addVip, param, function(error, result){
if(error)
{
console.log(error.message);
}else{
console.log('insert id: '+result.insertId);
}
});
connection.end();
刪除
var mysql = require('mysql');
var DATABASE = "node";
var TABLE="seckill"
var connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'12345',
port:'3306',
database: DATABASE
});
connection.connect();
var addVip = 'delete from seckill where seckill_id = 1005';
connection.query(addVip, function(error, result){
if(error)
{
console.log(error.message);
}else{
console.log('affectedRows: '+result.affectedRows);
}
});
connection.end();
查詢
var mysql = require("mysql");
var DATABASE = "node";
var TABLE="seckill"
var connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'12345',
port:'3306',
});
connection.connect();
connection.query('use '+DATABASE);
connection.query('select * from '+TABLE, function(error, results, fields){
if (error) {
throw error;
}
if (results) {
for(var i = 0; i < results.length; i++)
{
console.log('%s\t%s',results[i].name,results[i].end_time);
}
}
});
connection.end();
修改
var mysql = require('mysql');
var DATABASE = "seckill";
var connection = mysql.createConnection({
host:'127.0.0.1',
user:'root',
password:'12345',
port:'3306',
database: DATABASE
});
connection.connect();
var userSql = "update seckill set number = number-1 where seckill_id = ?";
var param = [1000, 2];
connection.query(userSql, param, function (error, result) {
if(error)
{
console.log(error.message);
}else{
console.log('affectedRows: '+result.affectedRows);
}
});
connection.end();
結束連線其實有兩種方法end(),destory();
- end()
end()方法在queries都結束後執行,end()方法接收一個回撥函式,queries執行出錯,仍然後結束連線,錯誤會返回給回撥函式err引數,可以在回撥函式中處理! - destory()
比較暴力,沒有回撥函式,即刻執行,不管queries是否完成!
使用連線池
在資料庫中執行如下程式碼建立一個儲存過程
DROP PROCEDURE IF EXISTS `P_SeckillInfo`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost` PROCEDURE `P_SeckillInfo`(IN ExtName VARCHAR(120),IN ExtNumber INT(11),OUT ExtReturnVal INT)
TOP: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET ExtReturnVal = 0; -- Failed
END;
START TRANSACTION;
INSERT INTO seckill(name, number) VALUES(ExtName,ExtNumber);
SET ExtReturnVal = 1;
SELECT ExtReturnVal;
COMMIT;
END
;;
DELIMITER ;
呼叫示例:
var mysql = require("mysql");
var pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password:'12345',
port:'3306',
database:'node'
});
//監聽connection事件
pool.on('connection', function(connection) {
connection.query('select * from seckill', function(error, results, fields){
if (error) {
throw error;
}
if (results) {
for(var i = 0; i < results.length; i++)
{
console.log('%s\t%s',results[i].name,results[i].end_time);
}
}
});
});
//連線池可以直接使用,也可以共享一個連線或管理多個連線(引用官方示例)
//直接使用
pool.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('The solution is: ', rows[0].solution);
});
//共享連線
function myQuery(sql)
{
pool.getConnection(function(err, connection) {
connection.query(sql, function(err, result) {
console.log(result);
//釋放連線
connection.release();
});
//Error: Connection already released,應該每次到連線池中再次獲取
// connection.query( 'SELECT * FROM seckill;', function(err, result) {
// console.log(result);
// connection.release();
// });
});
}
myQuery('SELECT * FROM seckill;');
myQuery('SELECT * FROM seckill;');
1.連線池的建立,使用createPool方法,options和createConntion一致;
2.其它連線池配置選項
- waitForConnections
當連線池沒有連線或超出最大限制時,設定為true且會把連線放入佇列,設定為false會返回error
connectionLimit
連線數限制,預設:10queueLimit
最大連線請求佇列限制,設定為0表示不限制,預設:0
斷開重連
示例程式碼:
var mysql = require('mysql');
var db_config = {
host: '127.0.0.1',
user: 'root',
password:'12345',
port:'3306',
database:'node'
};
var connection;
function handleDisconnect() {
connection = mysql.createConnection(db_config);
connection.connect(function(err) {
if(err) {
console.log('進行斷線重連:' + new Date());
setTimeout(handleDisconnect, 2000); //2秒重連一次
return;
}
console.log('連線成功');
});
connection.on('error', function(err) {
console.log('db error', err);
if(err.code === 'PROTOCOL_CONNECTION_LOST') {
handleDisconnect();
} else {
throw err;
}
});
}
handleDisconnect();
首先關閉mysql服務,然後執行程式,會一直列印斷線重連,當再次開啟mysql服務後,列印連線成功。
防止SQL注入
可以使用pool.escape()和connect.escape(),示例程式碼:
var mysql = require('mysql');
var pool = mysql.createPool({
host: '127.0.0.1',
user: 'root',
password:'12345',
port:'3306',
database:'node'
});
function myQuery(sql)
{
pool.getConnection(function(err,connection){
connection.query(sql,function(err,result){
//console.log(err);
console.log(result);
connection.release();
});
// connection.query('SELECT * FROM userinfo WHERE id = ' + pool.escape('5 OR ID = 6') ,function(err,result){
// //console.log(err);
// console.log(result);
// connection.release();
// });
});
}
myQuery('SELECT * FROM seckill WHERE seckill_id = ' + '1006 OR seckill_id = 1007');
myQuery('SELECT * FROM seckill WHERE seckill_id = ' + pool.escape('1006 OR seckill_id = 1007'));
結果可以看出,第1個query拼接條件可以被執行,而通過escape方法轉義後的忽略了後面的拼接的部分!
遇到的問題
編碼導致的問題
1366 (HY000): Incorrect string value: ‘\xC3\xEB\xC9\xB1’ for column ‘ExtName’ at row 1
字元編碼沒有統一的問題,檢視資料庫的編碼方式命令為:
mysql> show variables like ‘character%’;
從以上資訊可知資料庫的編碼為latin1,需要修改為gbk或者是utf8;