JDBC, что цель PreparedStatement # setNull

Я сделал эксперимент с таблицей, имеющей столбец VARCHAR с нулевыми значениями, пытающимися получить количество строк, имеющих определенный столбец NULL. Я использовал три формы:

форма A

SELECT COUNT(*) FROM buyers WHERE buye_resp IS NULL

форма B

 SELECT COUNT(*) FROM buyers WHERE buye_resp = ?

... где параметр предоставляется с помощью setString (1, null)

форма C

... как форма B, но параметр устанавливается с помощью setNull (1, java.sql.Types.VARCHAR)

Из трех форм, только форма A создала правильный результат, формы B и C оба возвращались 0 (код трех форм в конце сообщения). Что вызывает вопрос: какая цель setNull?

Тестирование, выполняемое в базе данных PostgreSQL 9.2.

код

private static int numOfRows_formA(Connection conn) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet         rs   = null;
    try {
        String pstmStr = "SELECT COUNT(*) FROM buyers WHERE buye_resp IS NULL";
        pstm = conn.prepareStatement(pstmStr);
        rs =  pstm.executeQuery();
        rs.next();
        return rs.getInt(1);
    } finally {
        DbUtils.closeQuietly(null, pstm, rs);
    }
}

private static int numOfRows_formB(Connection conn) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet         rs   = null;
    try {
        String pstmStr = "SELECT COUNT(*) FROM buyers WHERE buye_resp = ?";
        pstm = conn.prepareStatement(pstmStr);
        pstm.setString(1, null);
        rs = pstm.executeQuery();
        rs.next();
        return rs.getInt(1);
    } finally {
        DbUtils.closeQuietly(null, pstm, rs);
    }
}

private static int numOfRows_formC(Connection conn) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet         rs   = null;
    try {
        String pstmStr = "SELECT COUNT(*) FROM buyers WHERE buye_resp = ?";
        pstm = conn.prepareStatement(pstmStr);
        pstm.setNull(1, java.sql.Types.VARCHAR);
        rs = pstm.executeQuery();
        rs.next();
        return rs.getInt(1);
    } finally {
        DbUtils.closeQuietly(null, pstm, rs);
    }
}

Ответ 1

SQL использует тернарную логику, поэтому buye_responsible = ? всегда возвращает unknown (и никогда true), когда buye_responsible есть null. Для этого вам нужно IS NULL проверить null.

setNull() может использоваться, например, когда вам нужно передать инструкции null в INSERT и UPDATE. Поскольку такие методы, как setInt() и setLong(), принимают примитивные типы (int, long), вам понадобится специальный метод для передачи null в этом случае.

Ответ 2

В системе базы данных нуль не равен другому нульу, поэтому строка SELECT COUNT(*) FROM vat_refund.er_buyers WHERE buye_responsible = null не вернет никакой записи. Метод setNull() просто устанавливает нуль в позиции индекса. Sets the designated parameter to SQL NULL. Это из JAVA API. То есть он установит нулевой SQL для этого индекса, но не будет использовать функцию isNull() по вашему желанию. Вот почему для формы C вы также не получаете никакого результата.