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

Zee*_*mee 46 java null prepared-statement

声明是

SELECT * FROM tableA WHERE x = ?
Run Code Online (Sandbox Code Playgroud)

并通过java.sql.PreparedStatement'stmt'插入参数

stmt.setString(1, y); // y may be null
Run Code Online (Sandbox Code Playgroud)

如果y为null,则语句在每种情况下都不返回任何行,因为x = null它始终为false(应该是x IS NULL).一个解决方案是

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL)
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Pau*_*lin 37

我总是以你在问题中展示的方式完成它.两次设置相同的参数不是那么大的困难,是吗?

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL);
Run Code Online (Sandbox Code Playgroud)

  • 如果性能很重要,那么拥有两个单独的SQL可能更为可取,因为访问路径将根据您是否希望IS NULL而不同. (4认同)
  • 当然,这不是一个巨大的困难,特别是当你有 `x = ? 和 y = ? AND z = ?` 并且必须重写所有这些,因为 SQL 的绝妙想法是像对待其他任何东西一样对待 NULL。 (3认同)

Zee*_*mee 8

有一个非常未知的ANSI-SQL运算符IS DISTINCT FROM处理NULL值.它可以这样使用:

SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ?
Run Code Online (Sandbox Code Playgroud)

因此,只需设置一个参数.不幸的是,MS SQL Server(2008)不支持这一点.

另一个解决方案可能是,如果有一个值并且将永远不会被使用('XXX'):

SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX')
Run Code Online (Sandbox Code Playgroud)


dcp*_*dcp 5

只会使用两种不同的陈述:

声明1:

SELECT * FROM tableA WHERE x is NULL
Run Code Online (Sandbox Code Playgroud)

声明2:

SELECT * FROM tableA WHERE x = ?
Run Code Online (Sandbox Code Playgroud)

您可以检查变量并根据条件构建正确的语句.我认为这使代码更清晰,更容易理解.

编辑 顺便问一下,为什么不使用存储过程?然后你可以在SP中处理所有这些NULL逻辑,你可以简化前端调用的事情.