如何处理PreparedStatement中的(可能)空值?

时间:2010-11-18 13:16:30

标签: java null prepared-statement

陈述是

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)

但是我必须两次设置相同的参数。有更好的解决方案吗?

谢谢!

5 个答案:

答案 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等同,然后表达式处理所有其他可能性。 LNNVLOR更改为UNKNOWN,将TRUE更改为TRUE,将FALSE更改为FALSE,这与我们的完全相反想要,因此TRUE

在某些情况下,接受的解决方案对我来说在Oracle中不起作用,因为它是更大表达式的一部分,涉及NOT