Java 带有 IS NULL 的准备语句

Java Prepared Statement with IS NULL

假设我有一个 MySQL table 这样的:

VARCHAR 100 |变量 100 |变量 100

[ID][姓名][昵称][FAVORITE_COLOR]

1 约翰强尼红

2 埃里克 NULL GREEN

我想 select 在 Java 中使用以下准备好的语句 select 昵称为 NULL 的第二行:

statement = "SELECT * FROM my_table WHERE name = ? AND nickname = ?"

prepared = connection.prepareStatement(statement)
prepared.setString(1, "Eric")
prepared.setString(2, null)

result = prepared.executeQuery()

该查询无效。结果集为空。

我尝试的另一个选项是:

statement.setNull(2,java.sql.Types.VARCHAR)

这也不行,结果集为空。

最后,我尝试了一个不同的 SQL 但它显然是错误的并且 returns 行太多(因为它不够严格):

statement = "SELECT * FROM my_table WHERE name = ? AND (nickname IS NULL) OR (nickname = ?)"

在我的例子中,select行太多了。

所以我的问题是:如何使用 Java PreparedStatement,我可以 select 使用 MySQL 'IS NULL' 一行?

这是 SQL 数据库的众所周知的限制。对于大多数数据库,您必须编写 ... WHERE field IS NULL 来测试 field 的 NULL 值。 ... field = NULL... field = :param(其中 :param 是参数化查询的参数)都不会匹配 NULL 值。

所以唯一的解决办法是明确地写 field IS NULL 是你的查询。换句话说,您需要 2 个不同的查询,一个用于非空值(并且只有一个参数),另一个用于空值(和 2 个参数)。

statement = "SELECT * FROM my_table WHERE name = ? AND nickname = ?";
statement = "SELECT * FROM my_table WHERE name = ? AND nickname IS NULL";

你可以使用这个技巧(注意 JBNizet 解释的括号)

statement = "SELECT * FROM my_table WHERE name = ? AND (nickname = ? OR nickname IS NULL)";

如果您仍想为请求 NULL 值的查询使用 2 个参数。

https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to

NULL-safe equal. This operator performs an equality comparison like the = operator, but returns 1 rather than NULL if both operands are NULL, and 0 rather than NULL if one operand is NULL.

The <=> operator is equivalent to the standard SQL IS NOT DISTINCT FROM operator.

要使 null 有效,请将您的查询更新为: statement = "SELECT * FROM my_table WHERE name = ? AND nickname <=> ?"