SQL Query nên lựa chọn giải pháp nào? Bài viết này sẽ giúp bạn hiểu rõ hơn về 3 phương pháp tạo SQL Query
Vấn đề
Trong dự án bất kể chúng ta sử dụng loại cơ sở dữ liệu nào thì việc lựa chọn một thư viện (client) hỗ trợ kết nối và truy vấn dữ liệu là một điều hết sức cần thiết.
Có 3 phương pháp phổ biến mà các thư viện hỗ trợ truy vấn dữ liệu (SQL Query) đó là Raw Query, Query Builder và ORM. Mỗi phương pháp có cách thức triển khai khác nhau và ưu/nhược điểm khác nhau, tuỳ vào yêu cầu của dự án mà chúng ta sẽ lựa chọn để tận dụng tối đa sức mạnh của chúng.
Raw, Builder và ORM – Tạo SQL Query tối ưu?
Query Raw
Đúng như cái tên của nó, bạn sẽ trực tiếp viết lệnh SQL vào trong mã của dự án, nghĩa là bạn truy vấn dữ liệu SQL như thế nào thì trong mã của bạn viết như thế.
Ví dụ: mysql2.
const mysql = require('mysql2'); const connection = mysql.createConnection({ host: 'localhost', user: 'root', database: 'ncc' }); connection.query('SELECT * FROM `staff` WHERE `name` = "DuyNH" AND `age` > 18');
Có thể thấy raw query trực tiếp viết các câu SQL trong mã, điều này tăng tốc độ cho truy vấn vì bạn có thể dễ dàng viết những lệnh tối ưu nhất, đồng thời dễ đàng viết những câu truy vấn dài và phức tạp.
Tuy nhiên nếu dùng cách này bạn phải xác định được ngay từ đầu phải chọn cơ sở dữ liệu nào bởi việc đó ảnh hưởng đến việc lựa chọn thư viện. Không phải thư viện nào cũng kết nối được với MySQL hay Postgresql…
Query builder
Được cải tiến hơn về cú pháp, nó có thể là một thư viện hỗ trợ nhiều loại cơ sở dữ liệu khác như MySQL, Postgres, SQLServer… Nghĩa là một thư viện bạn có thể dễ dàng kết nối đến nhiều loại cơ sở dữ liệu khác nhau.
Query builder có một tổ hợp cú pháp truy vấn, bạn sẽ ráp chúng lại với nhau để lấy ra dữ liệu mà mình mong muốn. Cũng chính vì thế mà nó được gọi là builder.
Ví dụ có một thư viện hỗ trợ Query builder phổ biến là Knex.
const knex = require('knex')({ client: 'mysql', connection: { host: 'localhost', user: 'root', database: 'ncc' } }); const kQry = knex .select('*') .where("name", "DuyNH") .where("age", ">", 18) .from("staff");
Thay vì viết các lệnh raw, Query builder cung cấp các hàm chaining (chaining function) để hỗ trợ truy vấn. Điều đó giúp cho nó linh hoạt chuyển đổi sang lệnh SQL tương thích với từng loại cơ sở dữ liệu. Bạn cũng có thể dễ dàng xem lệnh raw bằng cách gọi hàm .toString()
.
kQry.toString(); // SELECT * FROM `staff` WHERE `name` = "DuyNH" AND `age` > 18;
Query builder giúp mã của bạn trông gọn gàng và có cấu trúc hơn. Cú pháp đồng nhất, hỗ trợ nhiều loại cơ sở dữ liệu. Phù hợp cho dự án sử dụng nhiều truy vấn phức tạp mà vẫn muốn cú pháp rõ ràng.
ORM (Object Relational Mapping)
Là phương pháp ánh xạ các bản ghi thành đối tượng.
Sequelize là một thư viện phổ biến hỗ trợ ORM. Cũng như Query builder, sequelize hỗ trợ cùng lúc nhiều loại cơ sở dữ liệu khác nhau.
ORM ban đầu sẽ phải viết nhiều mã hơn để khai báo lớp (Class) tương ứng với bảng (tables) trong cơ sở dữ liệu. Ví dụ đây là khai báo của bảng staff
:
const Staff = sequelize.define('staff', { name: { type: DataTypes.STRING, allowNull: false, }, age: { type: DataTypes.STRING, allowNull: false, } }
Sau đó để truy vấn rất đơn giản:
const users = await Staff.findAll({ where: { "name": "DuyNH", "age": { [Op.gt]: 18 }, });
Một lợi ích của ORM đó là trong kết quả truy vấn ở trên được ánh xạ trực tiếp với các dòng trong cơ sở dữ liệu, qua đó chúng ta có thể thao tác sửa, xoá dữ liệu trực tiếp từ chúng. Ví dụ:
users[0].setAttribute("name", "Duy DZai"); await users[0].save();
Bởi vì ORM đã ánh xạ từng dòng dữ liệu vào các đối tượng tương ứng thế nên việc bạn thao tác với các đối tượng cũng giống như đang thao tác với cơ sở dữ liệu mà không cần dùng đến bất kì mã SQL query nào.
Tổng kết
Trên đây là 3 phương pháp sử dụng Database client để sử dụng cơ sở dữ liệu. Tuỳ theo dự án mà chúng ta sẽ lựa chọn phương pháp phù hợp nhất. Raw query vẫn cho hiệu năng tối ưu nhất tuy nhiên phải viết nhiều mã. ORM dễ dàng truy vấn hơn nhưng lại khó sử dụng trong những trường hợp truy vấn phức tạp. Query builder cân bằng giữa hai cách tuy nhiên hãy xem xét kĩ trước khi sử dụng.