Cómo insertar y obtener el ID en una única consulta con MySQL y PHP

Cuando trabajamos con PHP y MySQL, a menudo necesitarás insertar un elemento nuevo en una tabla y obtener su ID para trabajar con él en tu script de PHP. Por tanto, el esquema del script sería:
  • Operaciones en PHP
  • Inserción de elemento en la BD
  • Recuperación del ID insertado
  • Más operaciones en PHP
Supongamos que tenemos una tabla de usuarios con los siguientes campos:

/* Tabla BD:
 *   usuario
 * Campos: 
 *   id     - int, auto_increment
 *   nombre - varchar
 *   edad   - int
 */

La solución más inmediata (y errónea) sería:
$bd = new mysqli(...);
$bd->query('INSERT INTO usuario (nombre, edad) VALUES ("Fran", 23)');
$result = $bd->query('SELECT MAX(id) FROM usuario');
$id = $result->fetch_assoc();

Pero esto es un terrible error que no puedes cometer nunca, no solo por la pérdida de rendimiento al realizar dos consultas, sino que también porque la segunda consulta no siempre se ejecutará inmediatamente después de la primera. Si piensas que al estar una después de otra se ejecutarán las dos en ese orden, permiteme hacerte pensar en la concurrencia de usuarios. Si dos usuarios entran a la vez en esta parte del script, puede ser que se ejecuten primero los dos INSERT y después los dos SELECT, devolviendo a ambos el mismo id. ¿Qué podemos hacer entonces? Existen varias opciones:
  • Bloquear la tabla al entrar al script. No recomendado por la pérdida de rendimiento
  • Usar un procedimiento almacenado (PROCEDURE). 
  • Usar insert_id de PHP
Si tenemos disponible la extensión mysqli de PHP (algo normal), bastará con acceder al atributo insert_id. Este atributo lo actualiza el servidor de forma automática cada vez que se hace una inserción y, lo que es mejor, con control de concurrencia.

Veamos un ejemplo usando la extensión mysqli de PHP con orientación a objetos:
$bd = new mysqli(...);
$bd->query('INSERT INTO usuario (nombre, edad) VALUES ("Fran", 23)');
$id = $bd->insert_id);
$bd->close();

Si estás usando mysqli por procedimientos, entonces deberías llamar a la función mysqli_insert_id():
$link = mysqli_connect(...);
mysqli_query($link, $query);
$id = mysqli_insert_id($link);
mysqli_close($link);

Eso es todo.

Detalles técnicos:
Lenguajes: PHP5, MySQL5
Referencias: extensión mysqli, insert_id

No hay comentarios:

Publicar un comentario