我正在开发一个Web应用程序(java-maven项目),我使用的查询存在问题。我的Web应用程序的UI有2个搜索字段:PTT
和ID
。
用户需要填写至少一个字段才能进行搜索。因此,两个字段都可以为空,但不能同时显示。
以前,我只有一个字段: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)均为空时,我就不需要了。
有什么建议我该如何解决这个问题?
答案 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.id
和t.ptr
的每个都有一个对应的参数。
总共将有4个参数。
您说t.id
或t.ptr
中的至少1 个有效值,因此有2种情况:
[1] t.id
和t.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.id
或t.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.ptr
和1
的对应值传递给无效值,如果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 != ?)