【问题标题】:How do I write queries with a null constraint in pg-promise properly?如何在 pg-promise 中正确编写具有空约束的查询?
【发布时间】:2020-08-30 17:33:55
【问题描述】:

在编写 Postgres 查询时,约束通常写成 WHERE a = $(a)WHERE b IN $(b:csv) 如果您知道这是一个列表。但是,如果值为null,则必须将约束写入WHERE x IS NULL。如果值为空,是否可以让查询自动格式化?

假设我可能想查找行 WHERE c = 1。如果我知道c1,我会写这样的查询

db.oneOrNone(`SELECT * FROM blah WHERE c = $(c), { c })

但如果c 变成null,则查询必须变成...WHERE c IS NULL

是否可以构造一个像WHERE $(c) 这样的通用查询,如果c1,它会自动格式化为WHERE c = 1,如果c 设置为null,它会自动格式化为WHERE c IS NULL

【问题讨论】:

    标签: node.js pg-promise


    【解决方案1】:

    您可以使用Custom Type Formatting 来帮助进行动态查询:

    const valueOrNull = (col, value) => ({
        rawType: true,
        toPostgres: () => pgp.as.format(`$1:name ${value === null ? 'IS NULL' : '= $2'}`,
                                        [col, value])
    });
    

    然后你可以把它作为格式化值传入:

    db.oneOrNone('SELECT * FROM blah WHERE $[cnd]', { cnd: valueOrNull('col', 123) })
    

    更新

    或者您可以仅对值本身使用自定义格式:

    const eqOrNull = value => ({
        rawType: true,
        toPostgres: () => pgp.as.format(`${value === null ? 'IS NULL' : '= $1'}`, value)
    });
    

    用法示例:

    db.oneOrNone('SELECT * FROM blah WHERE $1:name $2', ['col', eqOrNull(123)])
    //=> SELECT * FROM blah WHERE "col" = 123
    
    db.oneOrNone('SELECT * FROM blah WHERE $1:name $2', ['col', eqOrNull(null)])
    //=> SELECT * FROM blah WHERE "col" IS NULL
    

    请注意,为简单起见,我没有检查undefined,但您很可能会这样做,因为undefined 在内部也被格式化为null

    【讨论】:

    • 谢谢!我有这种感觉,但想确定一下。
    • @BrDaHa 我已经用额外的例子更新了答案;)
    【解决方案2】:

    根据值是否为NULL 来修改查询的一个非常有用的替代方法是使用IS [NOT] DISTINCT FROM。来自参考:

    对于非空输入,IS DISTINCT FROM<> 运算符相同。但是,如果两个输入都为 null,则返回 false,如果只有一个输入为 null,则返回 true。同样,IS NOT DISTINCT FROM= 对于非空输入相同,但当两个输入为空时返回 true,当只有一个输入为空时返回 false。因此,这些谓词实际上就像 null 是一个正常的数据值一样,而不是“未知”。

    简而言之,用IS NOT DISTINCT FROM代替=,用IS DISTINCT FROM代替<>

    这在比较两列时特别有用,其中任何一列都可能为空。

    请注意,IS [NOT] DISTINCT FROM 不能使用索引,因此某些查询可能性能不佳。

    【讨论】:

    猜你喜欢
    • 2019-09-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 2017-10-14
    • 2018-02-19
    相关资源
    最近更新 更多