sequelize之通过options生成sql语句

前言

在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);
    }).bind(model)(options);
};
  • 补充一个执行后获取sql语句的实例
let sql = '';
options.logging = function (str) {
    sql = str.substring(20, str.length-1); // 截取其中的sql语句
};
await models.OrderBasic.findAll(options); // options为查询时存入的参数

总结

  1. 获取sql语句的方法实际上是将源码中生成sql语句的部分提取出来了

  2. 目前还没有遇到sql解析错误,等遇到了再来更新

原文地址:https://www.cnblogs.com/xpengp/p/13164311.html