在预准备语句中绑定空变量

2022-09-04 21:02:31

我发誓这曾经有效,但在这种情况下不是。我正在尝试匹配 col1、col2 和 col3,即使其中一个或多个为空。我知道,在某些语言中,我不得不诉诸于诸如.这里需要这样做吗?((? is null AND col1 is null) OR col1 = ?)

        PreparedStatement selStmt = getConn().prepareStatement(
                "SELECT     * " +
                "FROM       tbl1 " +
                "WHERE      col1 = ? AND col2 = ? and col3 = ?");
        try
        {
            int col = 1;
            setInt(selStmt, col++, col1);
            setInt(selStmt, col++, col2);
            setInt(selStmt, col++, col3);
            ResultSet rs = selStmt.executeQuery();
            try
            {
                while (rs.next())
                {
                   // process row
                }
            }
            finally
            {
                rs.close();
            }
        }
        finally
        {
            selStmt.close();
        }

   // Does the equivalient of stmt.setInt(col, i) but preserves nullness.
    protected  static void setInt(PreparedStatement stmt, int col, Integer i)
    throws SQLException
    {
        if (i == null)
            stmt.setNull(col, java.sql.Types.INTEGER);
        else
            stmt.setInt(col, i);
    }

答案 1

这可能取决于 JDBC 驱动程序,但在大多数情况下,是的,您需要使用上面显示的更扩展的形式。

JDBC 预准备语句通常是围绕参数化查询的本机实现的相对较薄的包装器,即带有 ?代替参数被传递给查询编译器并进行编译,因此,稍后,当您调用 stmt.executeQuery() 时,语句无法从 a 调整为 。这与其说是JDBC的限制,不如说是SQL中NULL的语义。因为 SQL 未定义,如 原样。column = ?column IS NULLx = NULLx <> NULL

也就是说,一些JDBC驱动程序可能违反了SQL中的-ity概念,并允许setNull()将语句从转换为这种行为将是高度非标准的行为(尽管它可以通过编写某种查询预处理方法轻松完成)。NULL= ?IS NULL


答案 2

您使用的是哪个数据库?

但至少对于Oracle,相等(和不等式)永远不会匹配NULL,你必须写IS NOT NULL。