前言
在node.js web框架中使用sequelize来作为ORM是十分方便的。但是,有的时候我们需要用到子查询语句,使用sequelize无法完成需求。这时候,
如果你的查询语句不是很复杂,可以使用sequelize提供的query()方法直接执行生成的sql语句。
如果你的查询语句很复杂,但是子表查询结果数据不是很多,你可以先把子表查询结果获取到,在后端代码中进行数据处理,完成其它操作。
如果你的查询语句很复杂,并且子表查询结果数据非常多,不可能在代码中完成数据处理,简单的可以执行两次,第一次查询字表数据,获取到查询的sql语句,拼接好子查询语句后再查询一次即可。
由于sequelize只有执行查询后才可以在logging的回调函数中获取到生成的sql语句,这样就会多执行一次无用的数据库查询,下边写一个不执行查询获取sql语句的方法。
实例
- 以nodejs为例
- 根据options获取sql语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| const Utils = require('sequelize/lib/utils');
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); };
|
1 2 3 4 5
| let sql = ''; options.logging = function (str) { sql = str.substring(20, str.length-1); }; await models.OrderBasic.findAll(options);
|
总结
获取sql语句的方法实际上是将源码中生成sql语句的部分提取出来了
目前还没有遇到sql解析错误,等遇到了再来更新