openplanning

Kết nối cơ sở dữ liệu MySQL trong NodeJS

  1. Install MySQL Driver
  2. Kết nối MySQL
  3. Ví dụ: query(sql, callback)

1. Install MySQL Driver

Trước hết bạn cần tạo một project NodeJS, chẳng hạn ở đây tôi tạo một project với tên là NodeJSMySQL.
Tiếp theo bạn cần cài đặt thư viện MySQL cho project của bạn. Mở cửa sổ CMDCD tới thư mục gốc của project, và thực hiện lệnh dưới đây:
npm install mysql
Sau khi cài đặt xong, một thư mục node_modules sẽ được tạo ra trên project của bạn, thư mục này chứa các thư viện cần thiết để ứng dụng của bạn có thể kết nối cơ sở dữ liệu MySQL:

2. Kết nối MySQL

Ở bước trên bạn đã tạo thành công một project, và cài đặt các thư viện MySQL cho project này. Bây giờ tạo một ví dụ nhỏ, kết nối vào cơ sở dữ liệu MySQL. OK, Tạo một tập tin connection-example.js:
connection-example.js
var mysql = require('mysql');

console.log('Get connection ...');

var conn = mysql.createConnection({
  database: 'mytestdb',
  host: "localhost",
  user: "root",
  password: "12345"
});

conn.connect(function(err) {
  if (err) throw err;
  console.log("Connected!");
});
Chạy ví dụ:
node connection-example.js
Error: ER_NOT_SUPPORTED_AUTH_MODE
Khi chạy ví dụ trên, có thể bạn sẽ nhận được một thông báo lỗi như sau:
** Error **
E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Parser.js:80
        throw err; // Rethrow non-MySQL errors
        ^

Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
    at Handshake.Sequence._packetToError (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\sequences\Sequence.js:52:14)
    at Handshake.ErrorPacket (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\sequences\Handshake.js:130:18)
    at Protocol._parsePacket (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Protocol.js:279:23)
    at Parser.write (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Parser.js:76:12)
    at Protocol.write (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Protocol.js:39:16)
    at Socket.<anonymous> (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\Connection.js:103:28)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    --------------------
    at Protocol._enqueue (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Protocol.js:145:48)
    at Protocol.handshake (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\protocol\Protocol.js:52:23)
    at Connection.connect (E:\NODEJS\NodeJSMySQL\node_modules\mysql\lib\Connection.js:130:18)
    at Object.<anonymous> (E:\NODEJS\NodeJSMySQL\connection-example.js:11:6)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
Nguyên nhân của lỗi ở trên là do bạn sử dụng cơ sở dữ liệu MySQL quá mới (version >= 8.x). Các phiên bản MySQL cũ (5.x) sử dụng plugin xác thực (authentication plugin) là SHA256_PASSWORD. Phiên bản MySQL 8.x sử dụng plugin xác thực là SHA2_PASSWORD. Thư viện NodeJS MySQL chưa kịp thay đổi, nó đang sử dụng plugin xác thực SHA256_PASSWORD, và chưa hỗ trợ SHA2_PASSWORD.
Release
General availability
Latest minor version
Latest release
End of support
5.1
2008-11-14
5.1.73
2013-12-03
December 2013
5.5
2010-12-03
5.5.60
2018-04-19
December 2018
5.6
2013-02-05
5.6.40
2018-04-19
February 2021
5.7
2015-10-21
5.7.22
2018-04-19
October 2023
8.0
2018-04-19
8.0.11
2018-04-19
N/A
Để khắc phục lỗi trên bạn mở cửa sổ "MySQL Command Line Client" và thực thi lệnh dưới đây:
# Syntax:

ALTER USER 'my_username'@'my_host' IDENTIFIED WITH 'mysql_native_password' BY 'my_password';


# Example:

ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY '12345';
Một cách khác, bạn cũng có thể tạo một đối tượng Connection từ một connection_string:
** Create Connection from ConnectionString **
var connString = 'mysql://myuser:mypass@myhost/mdb?charset=utf8_general_ci&timezone=-0700';

var conn = mysql.createConnection(connString);

3. Ví dụ: query(sql, callback)

NodeJS MySQL API sử dụng phương thức query để thực hiện tất cả các hành động với cơ sở dữ liệu bao gồm:
  • DDL: Create DB, Table, ...
  • DML: Insert, Update, Query, Call Function, Procedure,...
** query method **
// query method:

query(sql, [values], callback)

// Example:

query(sql, [values], function(err, rows, fields)  {

});
Ví dụ dưới đây, chúng ta sẽ kết nối vào cơ sở dữ liệu MySQL và thực hiện các thao tác với code:
  1. Drop bảng EMPLOYEES nếu nó tồn tại.
  2. Tạo lại bảng EMPLOYEES.
  3. Trèn một vài bản ghi (record) vào bảng EMPLOYEES.
first-example.js
var mysql = require('mysql');

var conn = mysql.createConnection({
  database: 'mytestdb',
  host: "localhost",
  user: "root",
  password: "12345"
});


conn.connect(function(err) {
    if (err) {
        throw err;
    }
    console.log("Connected!");

    // Drop EMPLOYEES table if Exists!!
    var sql1 = "DROP TABLE IF EXISTS Employees ";

    conn.query(sql1, function(err, results) {
        if (err) throw err;
        console.log("Table EMPLOYEES dropped");
    });

    // Create EMPLOYEES Table.
    var sql2 = "CREATE TABLE Employees " +
        " (Id INT not null AUTO_INCREMENT, " +
        " Emp_No VARCHAR(20), " +
        " Full_Name VARCHAR(255), " +
        " Hire_Date DATE, " +
        " PRIMARY KEY (Id) )";

    conn.query(sql2, function(err, results) {
        if (err) throw err;
        console.log("Table Employees created");
    });

    var empNos = ["E01", "E02", "E03"];
    var fullNames = ["John", "Smith", "Gates"];
    var hireDates = ["22/10/2001", "11/11/2000", "12/12/1990"];

    // Insert Datas to EMPLOYEES.
    for (var i = 0; i < empNos.length; i++) {
        var sql3 = "Insert into Employees (Emp_No, Full_Name, Hire_Date) " //
            +
            " Values ('" + empNos[i] + "', '" + fullNames[i] + "', STR_TO_DATE('" + hireDates[i] + "', '%d/%m/%Y') )";

        conn.query(sql3, function(err, results) {
            if (err) throw err;
            console.log("Insert a record!");
        });
    }

});
Chạy ví dụ:
node first-example.js
Phương thức mysql.format(sql, replaces) giúp bạn chuẩn bị một mệnh đề SQL (SQL Statement), nó giúp bạn tạo ra một mênh đề SQL đơn giản và dễ nhìn hơn:
** mysql.format(sql_template, replaces) **
// Select * from EMPLOYEES where HIRE_DATE > STR_TO_DATE( '20/11/1995' , '%d/%m/%Y')
var sql_template = "Select * from ?? where ?? > STR_TO_DATE( ? , '%d/%m/%Y') ";

var replaces = ['EMPLOYEES', 'HIRE_DATE', '20/11/1995'];
sql = mysql.format(sql_template, replaces);

console.log("SQL="+ sql);
Ví dụ:
prepared-query-example.js
var mysql = require('mysql');

var conn = mysql.createConnection({
    database: 'mytestdb',
    host: "localhost",
    user: "root",
    password: "12345"
});


conn.connect(function(err) {
    if (err) throw err;

    console.log("Connected!");

    // Select * from EMPLOYEES where HIRE_DATE > STR_TO_DATE( '20/11/1995' , '%d/%m/%Y')
    var sql_template = "Select * from ?? where ?? > STR_TO_DATE( ? , '%d/%m/%Y') ";

    var replaces = ['EMPLOYEES', 'HIRE_DATE', '20/11/1995'];
    sql = mysql.format(sql_template, replaces);

    console.log("SQL=" + sql);
    console.log(" ************************ ");


    conn.query(sql, function(err, rows, fields) {
        if (err) throw err;
        for (var i = 0; i < rows.length; i++) {
            console.log("\n------ Row " + i + " ---- ");
            console.log(rows[i]);
            console.log("\n");
            console.log("  - Emp_No: " + rows[i].Emp_No)
            console.log("  - Full_Name: " + rows[i].Full_Name);
        }
    });

});
Data of rows:
[ RowDataPacket {
    Id: 1,
    Emp_No: 'E01',
    Full_Name: 'John',
    Hire_Date: 2001-10-21T17:00:00.000Z },

  RowDataPacket {
    Id: 2,
    Emp_No: 'E02',
    Full_Name: 'Smith',
    Hire_Date: 2000-11-10T17:00:00.000Z } ]
Data of fields
[ FieldPacket {
    catalog: 'def',
    db: 'mytestdb',
    table: 'EMPLOYEES',
    orgTable: 'employees',
    name: 'Id',
    orgName: 'Id',
    charsetNr: 63,
    length: 11,
    type: 3,
    flags: 16899,
    decimals: 0,
    default: undefined,
    zeroFill: false,
    protocol41: true },
  FieldPacket {
    catalog: 'def',
    db: 'mytestdb',
    table: 'EMPLOYEES',
    orgTable: 'employees',
    name: 'Emp_No',
    orgName: 'Emp_No',
    charsetNr: 33,
    length: 60,
    type: 253,
    flags: 0,
    decimals: 0,
    default: undefined,
    zeroFill: false,
    protocol41: true },
  FieldPacket {
    catalog: 'def',
    db: 'mytestdb',
    table: 'EMPLOYEES',
    orgTable: 'employees',
    name: 'Full_Name',
    orgName: 'Full_Name',
    charsetNr: 33,
    length: 765,
    type: 253,
    flags: 0,
    decimals: 0,
    default: undefined,
    zeroFill: false,
    protocol41: true },
  FieldPacket {
    catalog: 'def',
    db: 'mytestdb',
    table: 'EMPLOYEES',
    orgTable: 'employees',
    name: 'Hire_Date',
    orgName: 'Hire_Date',
    charsetNr: 63,
    length: 10,
    type: 10,
    flags: 128,
    decimals: 0,
    default: undefined,
    zeroFill: false,
    protocol41: true } ]