陈述是
SELECT * FROM tableA WHERE x = ?
并通过java.sql.PreparedStatement'stmt'
插入参数stmt.setString(1, y); // y may be null
如果y
为null,则语句在每种情况下都不返回任何行,因为x = null
始终为false(应为x IS NULL
)。
一种解决方案是
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL)
但是我必须两次设置相同的参数。有更好的解决方案吗?
谢谢!
答案 0 :(得分:36)
我总是以你在问题中展示的方式完成它。两次设置相同的参数并不是一件很大的困难,是吗?
SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL);
答案 1 :(得分:8)
有一个非常未知的ANSI-SQL运算符IS DISTINCT FROM
可以处理NULL值。它可以这样使用:
SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ?
因此只需要设置一个参数。不幸的是,MS SQL Server(2008)不支持此功能。
另一个解决方案可能是,如果有一个值,将永远不会使用('XXX'):
SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX')
答案 2 :(得分:5)
只会使用两种不同的陈述:
声明1:
SELECT * FROM tableA WHERE x is NULL
声明2:
SELECT * FROM tableA WHERE x = ?
您可以检查变量并根据条件构建正确的语句。我认为这使代码更清晰,更容易理解。
修改强> 顺便问一下,为什么不使用存储过程?然后你可以在SP中处理所有这些NULL逻辑,你可以简化前端调用的事情。
答案 3 :(得分:0)
如果您使用例如mysql,您可能会执行以下操作:
select * from mytable where ifnull(mycolumn,'') = ?;
然后你可以这样做:
stmt.setString(1, foo == null ? "" : foo);
您必须检查解释计划,看看它是否能提高您的表现。虽然这意味着空字符串等于null,因此它不会被授予它以满足您的需要。
答案 4 :(得分:0)
在Oracle 11g中,我是这样做的,因为foreach(Label l in tabPage1.Controls)
{
if(l.Click)
{
//Do something
}
}
在技术上评估为x = null
:
UNKNOWN
WHERE (x IS NULL AND ? IS NULL)
OR NOT LNNVL(x = ?)
之前的表达式负责将NULL与NULL等同,然后表达式处理所有其他可能性。 LNNVL
将OR
更改为UNKNOWN
,将TRUE
更改为TRUE
,将FALSE
更改为FALSE
,这与我们的完全相反想要,因此TRUE
。
在某些情况下,接受的解决方案对我来说在Oracle中不起作用,因为它是更大表达式的一部分,涉及NOT
。