【问题标题】:How can NULL and regular values be handled without using different prepared statements?如何在不使用不同的预处理语句的情况下处理 NULL 和常规值?
【发布时间】:2011-09-12 17:49:01
【问题描述】:

考虑这个简单的方法:

public ResultSet getByOwnerId(final Connection connection, final Integer id) throws SQLException {
    PreparedStatement statement = connection.prepareStatement("SELECT * FROM MyTable WHERE MyColumn = ?");
    statement.setObject(1, id);
    return statement.executeQuery();
}

示例方法应该从某个表中选择列值匹配的所有内容,应该很简单。 丑陋的细节是,为 id 传递 NULL 将导致一个空的 ResultSet,而不管数据库中有多少行,因为 SQL 将 NULL 定义为不是 euqaling anyting,甚至不是 NULL。 选择我知道的那些行的唯一方法是使用不同的 where 子句:

SELECT * FROM MyTable WHERE MyColumn IS NULL

不幸的是,使该方法在所有情况下都能正常工作的唯一方法似乎是拥有两种完全不同的执行路径,一种用于 id 参数为 null 的情况,另一种用于常规值。

这非常难看,当您有多个可以为空的列时,很快就会变得非常混乱。如何使用相同的代码路径/语句处理 NULL 和正常值?

【问题讨论】:

  • 我不使用 JDBC,但在 C# 中我通常设置它以便动态选择 = ? / IS NULL。参数(如果有)仍然通过准备好的语句绑定。
  • 如果您使用的是 SQL Server,则只需执行 SET ANSI_NULLS OFFfield = NULL 即可。
  • 考虑 Hibernate 或 JPA。它会让你从 JDBC 样板文件中解脱出来。

标签: java jdbc prepared-statement


【解决方案1】:

这个我没试过,但是发送空值到preparedStatements的方法是使用setNull()选项

   PreparedStatement statement = connection.prepareStatement("SELECT * FROM MyTable WHERE MyColumn = ?");
    if ( id == null)
       statement.setNull(1, java.sql.Types.INTEGER);
    else    
      statement.setObject(1, id);
    return statement.executeQuery();

编辑:感谢@Gabe 和@Vache 的回复。除了采用更冗长的方法来动态创建preparedstatement之外,似乎没有其他简单的方法可以做到这一点。

这样的东西应该可以工作--

String sql = " SELECT * FROM MyTable WHERE " + (id==null)?"MyColumn is null":"MyColumn = ?" ;
       PreparedStatement statement = connection.prepareStatement(sql);
        if ( id != null)
          statement.setObject(1, id);
        return statement.executeQuery();

【讨论】:

  • 在 ANSI SQL 中,MyColumn = NULL 永远不会为真,即使 MyColumn 具有 NULL 值。
  • 它将设置一个“SQL null”,但MyColumn = NULL 仍然不会返回任何结果。 setNull 主要用于插入查询。
【解决方案2】:

您可以使用这样的查询:

select * from MyTable where 
  case when ?1 is null then MyColumn is null else MyColumn = ?1

但它重用相同的参数,所以我不知道我提出的语法(?1)是否可行。

【讨论】:

    猜你喜欢
    • 2012-05-05
    • 2020-03-06
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 2017-10-06
    • 2021-11-11
    • 2017-07-14
    • 1970-01-01
    相关资源
    最近更新 更多