当所有参数均为空时,替代COALESCE

时间:2018-11-20 11:26:22

标签: java oracle plsql

我正在开发一个Web应用程序(java-maven项目),我使用的查询存在问题。我的Web应用程序的UI有2个搜索字段:PTTID。 用户需要填写至少一个字段才能进行搜索。因此,两个字段都可以为空,但不能同时显示。 以前,我只有一个字段:PTR,它显示的是大小为52的结果数组。(如果 我执行select * from users where ptr='smthing')。之后,我添加了ID字段并更新了我的查询,如下所示:

我在Web服务中执行以下查询:

String query= "SELECT t.ptr, t.id ";
        query+= "FROM users t ";
        query+= "WHERE t.ptr = COALESCE(?, t.ptr) AND " ;
        query+= "t.id = COALESCE(?, t.id) ";

,并在“准备好的语句”的帮助下设置字段。

现在,如果ptr字段已填写,但id字段在UI上留为空白(可以为null或空字符串),并且用户进行了搜索,结果数组的大小将变为30。与数据库比较 并且不会获取ID为null的行。因此,当coalesce的两个参数(?,t.ptr)均为空时,我就不需要了。 有什么建议我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

我认为您想要的逻辑是:

WHERE (t.ptr = ? OR ? IS NULL) AND 
      (t.id = ? OR ? IS NULL)

我建议使用命名参数,因此您不必两次传递它们。

答案 1 :(得分:1)

检查以下语句:

String query= "SELECT t.ptr, t.id ";
query+= "FROM users t ";
query+= "WHERE (t.ptr = ? OR 1 = ?)" 
query+= " AND " ;
query+= "(t.id = ? OR 1 = ?)";

您看到t.idt.ptr的每个都有一个对应的参数。
总共将有4个参数。
您说t.idt.ptr中的至少1 个有效值,因此有2种情况:

[1] t.idt.ptr均具有有效值。

对于两个对应的参数,您传递0,查询将变为:
"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0) AND (t.id = valueid OR 1 = 0)"
在WHERE部分:
t.ptr = valueptr OR 1 = 0等效于t.ptr = valueptr,并且
t.id = valueid OR 1 = 0等效于t.id = valueid
然后查询最终变为:
"SELECT t.ptr, t.id FROM users t WHERE t.ptr = valueptr AND t.id = valueid"

来自t.idt.ptr [2] 只有一个具有有效值,例如t.ptr

对于t.ptr的对应项,您通过0,对于t.id的项中,您通过-1(或任何其他不存在的值),对于t.id的项中,您通过1,查询变为:
"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0) AND (t.id = -1 OR 1 = 1)"
在WHERE部分:
t.ptr = valueptr OR 1 = 0等效于t.ptr = valueptr,并且
t.id = -1 OR 1 = 1等同于true,因为1 = 1始终是true
然后查询最终变为:
"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr OR 1 = 0)"
等效于:
"SELECT t.ptr, t.id FROM users t WHERE (t.ptr = valueptr)"

(在只有t.id具有有效值的情况下,您将t.ptr1的对应值传递给无效值,如果t.id传递给对方,则传递{{ 1}}。)

也许看起来很复杂,但是它正在运行,并且可以扩展超过2列。

答案 2 :(得分:1)

Oracle为此提供了构建功能。但是很难理解如何使用它。

lnnvl(a = b) = true if (a != b ) or ( a = null ) or (b = null)

就您而言

WHERE lnnvl(t.ptr != ? ) AND lnnvl( t.id != ?)

LNNVL