1

我正在函数内构建 SQL 查询。函数参数是我对 WHERE 子句的标准。参数也可以为空。

foo (1,2,3)           =>   SELECT x FROM y WHERE a=1 AND b=2 AND c=3;
foo (null, 2, null)   =>   SELECT x FROM y WHERE b=2;

我在代码中执行此操作的方法是在 WHERE 子句中添加第一个 alltime true(例如 1=1 或 NULL 为 NULL 或 2 > 1)

所以我不需要处理第一个 WHERE 条件在“WHERE”之后而所有其他条件都在“AND”之后的问题。

String sql="SELECT x FROM y WHERE 1=1";
if (a!=null)
{
  sql += " AND a="+a;
}

是否有比 1=1 更好的术语,或者我的其他样本明确具有始终真实的价值?TRUE 和 FALSE 不起作用。

4

6 回答 6

2

where即使没有条件,我也从来没有真正理解过强制条款的方法。如果您正在构建逻辑,请结合条件。如果结果字符串为空,则完全省略该where子句

许多应用程序语言都等效于concat_ws()-- 带有分隔符的字符串连接(join例如,在 Python 中)。因此,省略该where子句甚至不会导致代码复杂得多。

至于您的问题,Oracle 没有布尔值,因此1=1可能是最常见的方法。

于 2018-11-08T18:39:15.213 回答
2

Oracle 不支持 SQL 中的布尔类型。它存在于 PL/SQL 中,但不能在查询中使用。最简单的方法是 1=1 为真,0=1 为假。我不确定优化器是否会优化这些,但我怀疑性能影响可以忽略不计。我在运行时之前未知谓词数量的情况下使用了它。

我认为这种结构优于使用nvl, coalesce, decode, or的任何东西case,因为那些绕过正常索引并且我已经让它们导致复杂而缓慢的执行计划。

所以,是的,我会做类似你的事情(不确定你用什么语言构建这个查询;这不是有效的 PL/SQL。你也应该使用绑定变量,但那是另一回事):

sql = "SELECT x FROM y WHERE 1=1";
if (a != null)
{
    sql += " AND a=" + a;
}
if (b != null)
{
    sql += " AND b=" + b;
}
... etc.

我认为这比 Gordon Linoff 的建议要好,因为否则这会更复杂,因为您必须为每个谓词设置另一个子句来检查是否存在先前的谓词,即是否需要包含 the AND。它只是使代码更加冗长,以避免查询中出现单个琐碎的子句。

于 2018-11-09T01:19:52.730 回答
1

使用 NVL,以便您可以设置默认值。查找 NVL 或 NVL2。要么对你有用。退房:http ://www.dba-oracle.com/t_nvl_vs_nvl2.htm

于 2018-11-08T18:39:43.590 回答
0

在 sql 中,“默认 null”的标准方法是使用合并。假设您的输入是@p1、@p2 和@p3

然后

 select *
 from table
 where a = coalesce(@p1,a) and 
       b = coalesce(@p2,b) and 
       c = coalesce(@p3,c)

因此,如果(例如)@p1 为空,那么它将比较 a = a (始终为真)。如果@p1 不为null,那么它将过滤等于该值的值。

这样,null 就成为所有记录的“通配符”。

于 2018-11-08T18:40:02.347 回答
0

您还可以使用 decode 来获得所需的结果,因为它是 oracle

Select 
decode(a, 1, x,null),
decode(b, 2, x,null),
decode(c, 3, x,null)
from y
于 2018-11-08T18:52:08.683 回答
0

如果s 存在于括号外,OR如何在括号内使用AND

SELECT x 
  FROM y 
 WHERE ( a=:prm1 OR :prm1 is null) 
   AND ( b=:prm2 OR :prm2 is null) 
   AND ( c=:prm3 OR :prm3 is null);
于 2018-11-08T18:55:47.260 回答