【问题标题】:Ignoring Null input value when using a parameter with postgres使用带有 postgres 的参数时忽略 Null 输入值
【发布时间】:2023-03-06 03:01:01
【问题描述】:

鉴于这个简单的表格fiddle

 CREATE TABLE tbl (
  tbl_id             serial PRIMARY KEY,
  column_a       text NOT NULL,
  isactive bool NOT NULL
);
INSERT INTO tbl VALUES
  (1, 'a', true)
, (2, 'b', true)
, (3, 'c', false);

我看到一个用户使用这个 case 语句来抑制参数

SELECT
tbl_id,
column_a,
isactive
FROM tbl
WHERE CASE WHEN $1 IS NOT NULL THEN isactive = $1 ELSE 1=1 end AND
CASE WHEN $2 IS NOT NULL THEN column_a = $2 ELSE 1=1 end

我会建议他们使用这种语法

SELECT
tbl_id,
column_a,
isactive
FROM tbl
WHERE ($1 IS NULL OR isactive = $1) and 
($2 IS NULL OR column_a = $2)

我认为这些是等效的(并且可能更易于阅读)。你会做点不一样的吗?

【问题讨论】:

    标签: postgresql null


    【解决方案1】:

    您的建议肯定比CASE 语句更好,效率也不低。

    但是OR通常是WHERE条件下的问题,因为它使得PostgreSQL很难使用索引来加速查询。

    更好的解决方案是:

    • 仅当参数IS NOT NULL时才在查询中添加WHERE条件

    • 将查询写成UNION:

        SELECT tbl_id, column_a, isactive
        FROM tbl
        WHERE isactive = $1 AND column_a = $2
      UNION ALL
        SELECT tbl_id, column_a, isactive
        FROM tbl
        WHERE isactive = $1 AND $2 IS NULL
      UNION ALL
        SELECT tbl_id, column_a, isactive
        FROM tbl
        WHERE $1 IS NULL AND column_a = $2
      UNION ALL
        SELECT tbl_id, column_a, isactive
        FROM tbl
        WHERE $1 IS NULL AND $2 IS NULL;
      

      这看起来更长更复杂,但它可以使用isactivecolumn_a 上的索引。

    【讨论】:

    • 谢谢!我很感激
    猜你喜欢
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2019-05-05
    • 2019-12-30
    • 1970-01-01
    • 2014-12-12
    相关资源
    最近更新 更多