Statement Interface in Java
The Statement interface is used to send a fixed SQL string to the database and get the result. You create one from a connection with con.createStatement(), then call one of its three execute methods, depending on the kind of SQL. Statement is the simplest of JDBC's three statement types; PreparedStatement and CallableStatement extend it. Because a Statement takes complete SQL text, it suits SQL that contains no values from outside, such as creating tables. In this lesson, you will learn the three execute methods, what each returns, and how to read a key generated by the database.
Methods
| Method | Use it for | Returns |
|---|---|---|
executeQuery(sql) | SELECT | A ResultSet with the rows |
executeUpdate(sql) | INSERT, UPDATE, DELETE, and DDL such as CREATE TABLE | An int: the number of rows affected (0 for DDL) |
execute(sql) | Any SQL, when you don't know the kind in advance | A boolean: true if the result is a ResultSet |
getResultSet(), getUpdateCount() | After execute | The result set, or the row count |
getGeneratedKeys() | After an insert | A ResultSet holding keys the database generated |
addBatch(sql), executeBatch() | Many statements at once | See "Batch Processing in JDBC" |
setQueryTimeout(seconds) | Any | Limits how long a statement may run |
setMaxRows(n), setFetchSize(n) | Queries | Limit the rows returned; hint how many to fetch per network trip |
close() | Always | Releases the statement and its result set |
Example: The Three Execute Methods
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Stmt {
public static void main(String[] args) throws Exception {
try (Connection con = DriverManager.getConnection("jdbc:h2:mem:school");
Statement st = con.createStatement()) {
// execute: any SQL. Returns true only if there is a ResultSet.
boolean hasRows = st.execute("CREATE TABLE student ("
+ "id INT AUTO_INCREMENT PRIMARY KEY, "
+ "name VARCHAR(50), marks INT)");
System.out.println("execute(CREATE) returned " + hasRows);
// executeUpdate: INSERT, UPDATE, DELETE. Returns the row count.
int inserted = st.executeUpdate(
"INSERT INTO student (name, marks) VALUES "
+ "('Navika', 91), ('Srihitha', 84), ('Advitha', 78)");
int updated = st.executeUpdate(
"UPDATE student SET marks = marks + 2 WHERE marks < 90");
int deleted = st.executeUpdate(
"DELETE FROM student WHERE name = 'Nobody'");
System.out.println(inserted + " inserted, " + updated
+ " updated, " + deleted + " deleted");
// executeQuery: SELECT. Returns a ResultSet.
try (ResultSet rs = st.executeQuery(
"SELECT name, marks FROM student ORDER BY id")) {
while (rs.next()) {
System.out.println(rs.getString("name") + " "
+ rs.getInt("marks"));
}
}
// Getting the key the database generated.
st.executeUpdate(
"INSERT INTO student (name, marks) VALUES ('Navika A', 88)",
Statement.RETURN_GENERATED_KEYS);
try (ResultSet keys = st.getGeneratedKeys()) {
keys.next();
System.out.println("generated id: " + keys.getInt(1));
}
}
}
}execute(CREATE) returned false
3 inserted, 2 updated, 0 deleted
Navika 91
Srihitha 86
Advitha 80
generated id: 4Explanation:
executereturnedfalsebecauseCREATE TABLEproduces no rows.executeUpdatereturned the rows affected: 3 inserted; 2 updated (the two students below 90); 0 deleted, because no row matched. A count of 0 is not an error, so check it when a change must happen.executeQueryreturned the three rows, showing the updated marks.RETURN_GENERATED_KEYSasks the driver to keep the key that theAUTO_INCREMENTcolumn produced.getGeneratedKeys()returns it as a small result set: the new row got id 4.
One Statement, One Open ResultSet
A Statement can have only one open ResultSet at a time. Running another query on the same statement closes the previous result set. To read two result sets at once, for example in nested loops, use two statements.
When Not to Use Statement
A Statement receives the whole SQL as one string. If part of that string comes from a user, the user's text becomes part of the SQL command, which is the security hole known as SQL injection. For any SQL with values that vary, use PreparedStatement (see "PreparedStatement in Java" and "Statement vs PreparedStatement (SQL Injection)").
Use Statement for | Use PreparedStatement for |
|---|---|
DDL: CREATE TABLE, DROP INDEX | Anything with values from users, files or other systems |
| Fixed SQL with no parameters | SQL run many times with different values |
Common Mistakes
Using executeQuery for an INSERT, or executeUpdate for a SELECT. The driver throws SQLException.
Ignoring the update count. UPDATE ... WHERE id = 99 succeeds with 0 rows when id 99 doesn't exist.
Joining user input into the SQL string. Use PreparedStatement.
Reusing a statement while still reading its previous result set. The first result set is closed.
Interview Corner
What is the difference between execute, executeQuery and executeUpdate?
executeQuery is for statements that return a single result set, typically SELECT, and returns a ResultSet. executeUpdate is for INSERT, UPDATE, DELETE and DDL, and returns the number of affected rows (0 for DDL). execute can run any statement and returns true if the first result is a ResultSet or false if it is an update count; the result is then read with getResultSet() or getUpdateCount(). It is used when the type of SQL isn't known in advance or a statement returns multiple results.
Practice
- Easy: Use
executeto run aSELECT, check that it returnstrue, and read the rows fromgetResultSet(). - Harder: Delete every student below a pass mark with one
executeUpdateand print "n students removed", handling the case where n is 0.
Key Takeaways
Was this tutorial helpful?