前言
在node.js web框架中使用sequelize來作為ORM是十分方便的。但是,有的時候我們需要用到子查詢語句,使用sequelize無法完成需求。這時候,
如果你的查詢語句不是很復雜,可以使用sequelize提供的query()方法直接執行生成的sql語句。
如果你的查詢語句很復雜,但是子表查詢結果數據不是很多,你可以先把子表查詢結果獲取到,在后端代碼中進行數據處理,完成其它操作。
如果你的查詢語句很復雜,並且子表查詢結果數據非常多,不可能在代碼中完成數據處理,簡單的可以執行兩次,第一次查詢字表數據,獲取到查詢的sql語句,拼接好子查詢語句后再查詢一次即可。
由於sequelize只有執行查詢后才可以在logging的回調函數中獲取到生成的sql語句,這樣就會多執行一次無用的數據庫查詢,下邊寫一個不執行查詢獲取sql語句的方法。
實例
- 以nodejs為例
- 根據options獲取sql語句
const Utils = require('sequelize/lib/utils');
/**
* @parms model 當前表的模型實例
* @options {object} 查詢參數
*/
module.exports = function genSqlString(model, options) {
return (function (options) {
const tableNames = {};
tableNames[this.getTableName(options)] = true;
options = Utils.cloneDeep(options);
options = Object.assign({}, options, {
hooks: true,
rejectOnEmpty: true,
type: 'SELECT',
model: this,
tableNames: Object.keys(tableNames)
});
options.originalAttributes = this._injectDependentVirtualAttributes(options.attributes);
if (options.include) {
options.hasJoin = true;
this._validateIncludedElements(options, tableNames);
if (
options.attributes
&& !options.raw
&& this.primaryKeyAttribute
&& !options.attributes.includes(this.primaryKeyAttribute)
&& (!options.group || !options.hasSingleAssociation || options.hasMultiAssociation)
) {
options.attributes = [this.primaryKeyAttribute].concat(options.attributes);
}
}
if (!options.attributes) {
options.attributes = Object.keys(this.rawAttributes);
options.originalAttributes = this._injectDependentVirtualAttributes(options.attributes);
}
this.options.whereCollection = options.where || null;
Utils.mapFinderOptions(options, this);
options = this._paranoidClause(this, options);
return this.QueryGenerator.selectQuery(this.getTableName(options), options, this);
}).call(model, options);
};
- 補充一個執行后獲取sql語句的實例
let sql = '';
options.logging = function (str) {
sql = str.substring(20, str.length-1); // 截取其中的sql語句
};
await models.OrderBasic.findAll(options); // options為查詢時存入的參數
總結
-
獲取sql語句的方法實際上是將源碼中生成sql語句的部分提取出來了
-
目前還沒有遇到sql解析錯誤,等遇到了再來更新