【问题标题】:How to create search queries in SQL with optional search parameters?如何使用可选的搜索参数在 SQL 中创建搜索查询?
【发布时间】:2016-05-31 04:50:46
【问题描述】:

是否有使用可选参数创建搜索查询的通用模式?我在想我们应该能够构建一个多部分的where 子句,但取消未指定的部分。此外,某些查询参数可能需要连接,如果未指定关联的查询参数,我想取消它们。

示例(查看完整代码here

想想人员配备领域。它由项目、需求、人员和技能组成。我们希望根据以下条件搜索需求:

1. min_start_date
2. max_start_date
3. project_id
4. project_location
5. skill_id

以下是相关表格:

CREATE TABLE projects (
  id SERIAL PRIMARY KEY,
  name VARCHAR(64),
  location VARCHAR(3) NOT NULL
);

CREATE TABLE needs (
  id SERIAL PRIMARY KEY,
  start_date TIMESTAMPTZ,
  end_date TIMESTAMPTZ,
  project_id INTEGER NOT NULL,
  skill_id INTEGER NOT NULL
);

CREATE TABLE skills (
  id SERIAL PRIMARY KEY,
  name VARCHAR(64) NOT NULL
);

这是搜索的查询:

\set min_start_date '2016-08-01T00:00:00-04'
\set max_start_date '2016-08-31T00:00:00-04'
\set project_id 71
\set project_location 'DEN'
\set skill_id 4

SELECT n.id, n.start_date, n.end_date
FROM   needs n
       LEFT OUTER JOIN projects p
                    ON n.project_id = p.id
WHERE  n.start_date >= :'min_start_date'
  AND  n.start_date <  :'max_start_date'
  AND  p.id = :'project_id'
  AND  p.location = :'project_location'
  AND  s.id = :'skill_id'
ORDER  BY n.start_date, p.id, s.id;

我想要的是根据指定的查询参数使 where 子句的部分无效的能力。如果没有指定搜索参数project_location,也应该不需要执行join。

编辑

根据 Neil McGuigan 的评论,我尝试了这个:

\set min_start_date 2016-08-01T00:00:00-04

SELECT *
FROM   needs n
WHERE  (:'min_start_date' IS NULL OR n.start_date >= :'min_start_date');

这可以正常工作并产生所需的结果,但是当我将 min_start_date 的值更改为 NULL 时:

\set min_start_date NULL

我从 PostgreSQL 收到以下错误:

ERROR:  invalid input syntax for type timestamp with time zone: "NULL"
LINE 8: WHERE  ('NULL' IS NULL OR n.start_date >= 'NULL')
                                                  ^

基本上我无法为 OR 的两边提供正确的类型。不确定如何指定 NULL 参数值,SQL 语句是否可以工作。

【问题讨论】:

  • 如果您为不需要的参数提供 NULL 值当然是可能的,但您应该动态生成查询并且不包括这些部分。
  • 当您说动态生成查询时,您的意思是字符串连接以每次都生成自定义查询吗?那意味着根本没有准备好的陈述,对吗?我希望有更好的方法。
  • 您似乎在引用您的绑定变量 - 没有必要 - 您正在检查字符串 'NULL' 是否为 NULL,或者日期是否大于或等于字符串。
  • 好吧,我被两种方式都困住了,如果我引用它们,那么我将 'NULL'NULL 进行比较,如果我不引用它们,那么我在 WHERE 子句中出现语法错误:语法“T00”或附近的错误:WHERE (2016-08-01T00:00:00-04...
  • 代码在这里签到,如果你想试试看:github.com/sapientglobalmarkets/staffer/blob/master/staffer-sql/…

标签: sql postgresql


【解决方案1】:

是的:

where
   (column1Value is null OR column1 = column1Value)
   and (column2Value is null OR column2 = column2Value)
   ...

连接条件是任何旧谓词,因此您可以根据需要将其复杂化

【讨论】:

  • 谢谢尼尔。这很棒。我几乎可以看到它工作。但是,当我尝试它时,PostgreSQL 在 NULL 周围加上引号并将其解释为字符串。请查看我上面的编辑以及错误消息。
  • 看来 psql 变量只是字符串替换(如宏)。它们不是具有类型的一流变量。我想当我用编程语言做这件事时,我可以让你的基本概念发挥作用。将您的答案标记为正确。
猜你喜欢
  • 1970-01-01
  • 2010-09-24
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多