Nest.js + TypeOrm:原始SQL查询及其参数绑定

上一篇

Nest.js + TypeOrm:安装、编写实体类

DataSource.query 进行参数化原始SQL查询

使用 DataSource.query(),注意,如果是 PostgreSQL,则参数占位符不能使用问号 ?,只能使用 $n,并且在没有表名的情况下需要指定类型:
否则,会出现错误:PostgreSQL - ERROR: could not determine data type of parameter $1,参见:https://blog.51cto.com/u_10980859/5303844

@Injectable()
export class PermissionsService {
    constructor(
        private readonly dataSource: DataSource,
    ) { }

    async check(id: number, body: CheckDTO) {
        let sql = `SELECT $1::int4`;
        let parameters = [id];
        try {
            let [row1] = await this.dataSource.query(sql, parameters);
            console.log(row1);
        } catch(e) {
            // console.log(e);
        }
        return false;
    }
}

关于绑定占位符的讨论:https://github.com/typeorm/typeorm/issues/881

取决于底层数据库驱动程序:

Oracle: query('SELECT * FROM table WHERE name = :name', [ { val: 'something' } ])
MySQL: query('SELECT * FROM table WHERE name = ?', [ 'something' ])
MSSQL: query('SELECT * FROM table WHERE name = @0', [ 'something' ])
Postgres: query('SELECT * FROM table WHERE name = $1', [ 'something' ])

DataSource.createQueryBuilder 进行参数化原始SQL查询

https://dev.to/avantar/how-to-output-raw-sql-with-filled-parameters-in-typeorm-14l4

PostgreSQL JSONB 运算符

https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSONB-OP-TABLE

Operator Right Operand Type Description Example
@> jsonb Does the left JSON value contain within it the right value? '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb
<@ jsonb Is the left JSON value contained within the right value? '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb
? text Does the key/element string exist within the JSON value? '{"a":1, "b":2}'::jsonb ? 'b'
?| text[] Do any of these key/element strings exist? '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c']
?& text[] Do all of these key/element strings exist? '["a", "b"]'::jsonb ?& array['a', 'b']

为什么强调这个?因为我一顿操作,结果发现其实只要一个 ?| 运算就可以解决问题:

@Injectable()
export class PermissionsService {
    constructor(
        private readonly dataSource: DataSource,
    ) { }

    /** 添加SQL参数,并返回其占位符 */
    private pushParam(parameters: any[], el: any): string {
        return `$${parameters.push(el)}`;
    }

    async check(id: number, body: CheckDTO) {
        let parameters = [];
        let roles = ``;
        if (body.roles && body.roles.length > 0) {
            roles = `AND (${
                body.roles.map(
                    it => `roles ? ${this.pushParam(parameters, it)}`
                )
                .join(' OR ')
            })`
        }
        let sql = `SELECT 1 as pass FROM t_user
                    WHERE id = ${this.pushParam(parameters, id)}
                    ${roles}`;
        //let [{ pass }]= await this.dataSource.query(sql, parameters); // 可能因为 undefined 而解构失败
        //console.log(pass);
        //return pass === 1;
        let [row]= await this.dataSource.query(sql, parameters);
        return row?.pass === 1;
    }
}

更多请参考:https://www.cnblogs.com/alianbog/p/5658156.html

posted @ 2023-06-09 15:00  develon  阅读(946)  评论(0编辑  收藏  举报