entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

3votos

MAX(id) vs last_insert_id en PHP

Tengo una tabla pedidos y otra descripcionPedidos, al momento de guardar el pedido consigo el id mediante $maxID = 'SELECT MAX(id) from pedidos;'

lo utilizo para concatenarle un string random de longitud 4 para un folio, después guardo $maxId en la tabla descripcionPedidos.
Usuarios concurrentes 10 por segundo.

Cuál es la mejor forma, en cuanto a su experiencia; y rendimiento. Seguir utilizando SELECT MAX o last_insert_id

migbriones comentado Dic 23, 2016

Muchas gracias compañeros @Leonardo-Tadei, @magarzon siempre es un placer leer sus comentarios e implementarlos para futuros proyectos. Gracias nuevamente y sigan compartiendo su conocimiento con nosotros.

2 Respuestas

3votos

magarzon Puntos16220

Se debe usar LAST_INSERT_ID.

La función Max no te garantiza que dos consultas concurrentes te den exactamente el mismo resultado, y tienes un nivel de peticiones por segundo en el que es muy probable que se dé el caso.

Saludos.

2votos

Leonardo-Tadei Puntos196870

Hola @migbriones,

da lo mismo: en ambos casos para que esta operación sea consistente, deben estar en INSERT, la consulta posterior y el INSERT usando el valor de la consulta en una transacción.

Ahora bien: no tiene mucho sentido el hacer la consulta para obtener el ID que estás planteando, ya que en PHP el viejo mysql* y las actuales mysqli* devuelven el ID autoincremental generado como resultado del INSERT, con lo que no puede haber problemas de concurrencia.

Este es el escenario típico de uso y no hace falta la función LAST_INSERT_ID para implementarlo. La función MAX() tiene sentido en la implementación cuando el valor no se corresponde con el ID, por ejemplo, cuando te hace falta encontrar un máximo por empleado o por punto de venta.

Saludos cordiales

magarzon comentado Dic 19, 2016

Discrepo @Leonardo-Tadei

mysql_query y mysqli_query no te devuelven el ID autoincremental generado en el caso de un INSERT, solo te devuelven true o false.

Y ya hablamos el otro día en otra pregunta que para el caso de usuarios concurrentes se debe usar last_insert_id.

Leonardo-Tadei comentado Dic 19, 2016

Hola @migbriones y @magarzon,

PHP sí te devuelve el último ID generado automáticamente si luego de ejecutar una query que inserte una fila que tenga un campo autoincremental, se ejecuta la función
mysql_insert_id() o http://php.net/manual/es/mysqli.insert-id.php o PDO::lastInsertID

No hace falta ejecutar ninguna otra query, ya que PHP obtiene y guarda ese valor internamente.

El valor de estas funciones cambia o desaparece si se ejecuta cualquier otra query o si termina el script y es safe thread.

Saludos cordiales

magarzon comentado Dic 19, 2016

Nuevamente discrepo @Leonardo-Tadei.

La función mysql_insert_id() es más o menos equivalente a LAST_INSERT_ID() de mysql, efectivamente, porque de hecho es una especie de wrapper, por lo que al final está haciendo una especie de consulta al motor de base de datos para obtener el último id insertado por esa conexión (no es un SELECT last_insert_id() pero como si lo fuera). Y además tiene el inconveniente de que el valor que te devuelve es un int, por lo que si tu columna id es un bigint (64 bits), te puede devolver un resultado erróneo. Tampoco funciona si el insert lo has hecho utilizando procedimientos almacenados.

Si vas a utilizar ese last insert id como valor en un insert/update posterior, lo mejor es utilizar directamente la función LAST_INSERT_ID(), te ahorras esa miniconsulta y te evitas problemas con los bigint.

Leonardo-Tadei comentado Dic 20, 2016

De las funciones que menciono en mi respuesta, solo mysql_insert_id() devuelve un entero, lo que podría dar problemas de precisión en números grandes si PHP está corriendo sobre un equipo de 32 bits.

En cambio mysqli_insert_id() devuelve un entero si es menor a max_int y un string si es mayor, así que no da problemas.

Por otra parte PDO::lastInsertID devuelve siempre el número como un string, así que nunca da problemas de tamaño con los bigint.

Saludos cordiales.

magarzon comentado Dic 20, 2016

Aparte de que personalmente no me gusta que una función devuelva diferentes tipos de datos (y de hecho PHP, con la versión 7, se encamina hacia un lenguaje fuertemente tipado), de todas formas sigues teniendo el "problema" de que haces una consulta de más a la base de datos (un round trip, como dicen los americanos), que te puedes ahorrar si usas directamente LAST_INSERT_ID

Leonardo-Tadei comentado Dic 20, 2016

Hola @magarzon,

acá me pierdo un poco: no implica el mismo round trip ejecutar una query con el LAST_INSERT_ID ???

Además, una de las ventajas adicionales de llamar a la función PHP es que en caso de una query con el formato INSERT ... ON DUPLICATE... la función LAST_INSERT_ID da un resultado erróneo cuando se ejecuta un UPDATE y las funciones de PHP no fallan.

Es un tema con muchos matices... y eso que todavía no tuve tiempo de ver el código fuente de la implementación de PHP!

magarzon comentado Dic 20, 2016

Las funciones de PHP tienen que hacer una consulta a través de la conexión abierta con la base de datos, es decir, tienen que hacer una comunicación con ella, mientras que el LAST_INSERT_ID() se ejecuta como parte de la misma query/insert/update, es solo acceder a un registro, ya estás en la misma base de datos.

Por poner un ejemplo, lo que quería hacer nuestro amigo de insertar, coger el último id, y actualizar, requiere de 3 "comunicaciones" con la base de datos en el caso de usar las funciones de PHP, y de solo 2 en el caso de usar el LAST_INSERT_ID

Por favor, accede o regístrate para responder a esta pregunta.

¿Conoces alguien que puede responder?
¡Comparte esta pregunta!


Actividad Reciente

¿Eres Usuario Apple?

...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta