Get query from java.sql.PreparedStatement

This is nowhere definied in the JDBC API contract, but if you're lucky, the JDBC driver in question may return the complete SQL by just calling PreparedStatement#toString(). I.e.

System.out.println(preparedStatement);

To my experience, the ones which currently do so are at least the PostgreSQL 8.x and MySQL 5.x JDBC drivers.

In the case that your JDBC driver doesn't support it, your best bet is using a statement wrapper which records all calls to setXxx() methods and finally populates a SQL string on toString() based on the recorded information. An existing library which does that is P6Spy. In the meanwhile, post an enhancement request to the development team of your JDBC driver and hope that they'll implement the desired toString() behavior as well.


You could try calling toString() on the prepared statement after you've set the bind values.

PreparedStatement statement = connection.prepareStatement(aSQLStatement);
System.out.println("Before : " + statement.toString());
query.setString(1, "Hello");
query.setString(2, "World");
System.out.println("After : " + statement.toString());

This works when you use the JDBC MySQL driver, but I'm not sure if it will in other cases. You may have to keep track of all the bindings you make and then print those out.

Sample output from above code.

Before : com.mysql.jdbc.JDBC4PreparedStatement@fa9cf: SELECT * FROM test WHERE blah1=** NOT SPECIFIED ** and blah2=** NOT SPECIFIED **
After : com.mysql.jdbc.JDBC4PreparedStatement@fa9cf: SELECT * FROM test WHERE blah1='Hello' and blah2='World'

For those of you looking for a solution for Oracle, I made a method from the code of Log4Jdbc. You will need to provide the query and the parameters passed to the preparedStatement since retrieving them from it is a bit of a pain:

private String generateActualSql(String sqlQuery, Object... parameters) {
    String[] parts = sqlQuery.split("\\?");
    StringBuilder sb = new StringBuilder();

    // This might be wrong if some '?' are used as litteral '?'
    for (int i = 0; i < parts.length; i++) {
        String part = parts[i];
        sb.append(part);
        if (i < parameters.length) {
            sb.append(formatParameter(parameters[i]));
        }
    }

    return sb.toString();
}

private String formatParameter(Object parameter) {
    if (parameter == null) {
        return "NULL";
    } else {
        if (parameter instanceof String) {
            return "'" + ((String) parameter).replace("'", "''") + "'";
        } else if (parameter instanceof Timestamp) {
            return "to_timestamp('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS").
                    format(parameter) + "', 'mm/dd/yyyy hh24:mi:ss.ff3')";
        } else if (parameter instanceof Date) {
            return "to_date('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").
                    format(parameter) + "', 'mm/dd/yyyy hh24:mi:ss')";
        } else if (parameter instanceof Boolean) {
            return ((Boolean) parameter).booleanValue() ? "1" : "0";
        } else {
            return parameter.toString();
        }
    }
}