Cómo insertar, modificar y borrar datos

Con executeUpdate es posible realizar queries que no devuelvan resultados, sino que actualicen una tabla, para así obtener acceso al contador de filas insertadas, modificadas o borradas. Podemos usar ese método para hacer un INSERT, UPDATE y DELETE en SQL.

Para hacer inserciones, modificaciones y borrados de filas en JDBC, lo haremos como se hace con las queries que hemos visto hasta ahora: con un statement, invocando a createStatement(). Sí, también se pueden juntar inserciones con sentencias preparadas si empleamos prepareStatement en vez de createStatement.

Para hacer este tipo de operaciones, haremos uso del método executeUpdate(), que ejecuta una sentencia SQL con un INSERT, UPDATE o DELETE. Pese al nombre, es compatible con inserciones y borrados. Su propósito es modificar la base de datos, de ahí el nombre.

El método executeUpdate() acepta como parámetro el String con la sentencia SQL que vayamos a invocar, y devuelve un número con el total de registros insertados, modificados o borrados.

Una cosa a considerar es que, en realidad, tanto executeQuery() como executeUpdate() son atajos que invocan al método execute(). Este método también sirve para ejecutar una sentencia del tipo que sea, y se usa en colaboración de otros dos métodos:

  • getResultSet(), que devuelve el ResultSet de la última ejecución.
  • getUpdateCount(), que devuelve el número de filas modificadas en la última operación de actualización de bases de datos.

En definitiva, el pseudocódigo de los métodos executeQuery() y executeUpdate() es algo como esto:

// Esto es un pseudocódigo: no tengo ni idea de si es exactamente así o no.
public ResultSet executeQuery(String sql) {
  execute(sql);
  return getResultSet();
}

public int executeUpdate(String sql) {
  execute(sql);
  return getUpdateCount();
}

Ejemplos de INSERT, UPDATE y DELETE

Con lo que te he contado, ya puedes ver que executeUpdate() te vale para hacer inserciones. Dada la siguiente sentencia SQL:

INSERT INTO pacientes(nombre, apellido, fecha_nacimiento)
  VALUES ('Pepito', 'Pérez', '2008-08-14');

El siguiente código Java nos permitiría insertar ese registro en la tabla:

try (Connection conn = openConnection();
     Statement stmt = conn.createStatement()) {
  var sql = "INSERT INTO pacientes(nombre, apellido, fecha_nacimiento) VALUES ('Pepito', 'Pérez', '2008-08-14');";
  var result = stmt.executeUpdate(sql);
  System.out.println("Se han insertado " + result + " filas");
} catch (SQLException ex) {
  ex.printStackTrace();
}

Al ejecutar este fragmento de código, debería aparecer un mensaje como Se han insertado 1 filas.

Ten en cuenta también que muchos dialectos de SQL permiten el uso de palabras clave como RETURNING u OUTPUT para devolver cosas tras hacer un insert. Por ejemplo, podrías recuperar el ID del registro que se acaba de insertar en base de datos mediante una sentencia como la sigueinte para PostgreSQL:

INSERT INTO pacientes(nombre, apellido, fecha_nacimiento)
  VALUES ('Pepito', 'Pérez', '2008-08-14')
  RETURNING id;

De modo que en algunas ocasiones te puede compensar recuperar el ResultSet si quieres sacar el ID de la fila insertada.

Para hacer un UPDATE con JDBC es más de lo mismo:

try (Connection conn = openConnection();
     Statement stmt = conn.createStatement()) {
  var sql = "UPDATE pacientes SET nombre = 'Guillermo' WHERE id = 13";
  var result = stmt.executeUpdate(sql);
  System.out.println("Se han actualizado " + result + " filas");
} catch (SQLException ex) {
  ex.printStackTrace();
}

E igual con DELETE:

try (Connection conn = openConnection();
     Statement stmt = conn.createStatement()) {
  var sql = "DELETE FROM pacientes WHERE id > 10";
  var result = stmt.executeUpdate(sql);
  System.out.println("Se han eliminado " + result + " filas");
} catch (SQLException ex) {
  ex.printStackTrace();
}

No te olvides de poner el WHERE en el DELETE FROM.

INSERTS, UPDATES y DELETES preparados

Si vas a insertar elementos en la base de datos usando datos del mundo exterior, ten en cuenta que también tienes que proteger tus queries ante posibles valores inapropiados. Es por ello que deberías usar prepared statements también cuando vayas a hacer una inserción, una actualización o un borrado.

Estoy pensando fundamentalmente en aplicaciones que te permitan crear o actualizar datos usando como entrada algo que ponga el usuario, o borrar registros a partir de su ID.

Para ello, deberás utilizar también prepareStatement(). El formato es igual que lo que te contaba en la lección sobre prepared statements. Tendrás que especificar la plantilla de tu sentencia SQL, dejando placeholders en los lugares donde luego quieras insertar el parámetro que te entreguen desde fuera.

Por ejemplo, di que quieres crear registros de paciente, especificando su nombre, apellidos y fecha de nacimiento. La plantilla de tu sentencia SQL será la siguiente:

INSERT INTO pacientes(nombre, apellidos, fecha_nac) VALUES(?, ?, ?)

Observa que como values, he especificado una tupla donde los tres valores de las tres columnas son una interrogación. Este es el placeholder. Cuando luego aplique la plantilla, tendré que especificar los tres valores para las tres columnas por separado, de manera similar a como se hace con una consulta de tipo SELECT. Cuando termines de especificar los valores, utiliza executeUpdate() como método para aplicar la plantilla y ejecutarla.

record Paciente(String nombre, String apellidos, LocalDate fechaNac) { }

public void insertarPaciente(Connection conn, Paciente p) {
  var prepared = "INSERT INTO pacientes(nombre, apellidos, fecha_nac) VALUES(?, ?, ?)");

  try (PreparedStatement pstmt = conn.prepareStatement(prepared)) {
    pstmt.setString(1, ps.nombre());
    pstmt.setString(2, ps.apellido());
    pstmt.setObject(3, ps.fechaNac());
    pstmt.executeUpdate();
  }
}
Lista de reproducción
  1. 1
    ¿Qué es JDBC?
    5 minutos
  2. 2
    Configurar un driver
    7 minutos
  3. 3
    Deja de poner Class.forName
    8 minutos
  4. 4
    Conectarse en JDBC
    10 minutos
  5. 5
    Cómo ejecutar consultas
    10 minutos
  6. 6
    PreparedStatement, ¿por qué usarlo?
    11 minutos
  7. 7
    Cómo insertar, modificar y borrar datos
    10 minutos
  8. 8
    Transacciones
    12 minutos
  9. 9
    Cursores avanzados
    11 minutos
  10. 10
    ResultSets concurrentes
    10 minutos
  11. 11
    DataSource: así se usa JDBC en la vida real
    14 minutos
  12. 12
    ¿Se sigue usando JDBC?
    10 minutos