elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Desarrollo Web
| | |-+  PHP (Moderador: #!drvy)
| | | |-+  [solucionado] mysqli rollback todos los insert si uno falla
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [solucionado] mysqli rollback todos los insert si uno falla  (Leído 3,043 veces)
gAb1


Desconectado Desconectado

Mensajes: 731


Ver Perfil
[solucionado] mysqli rollback todos los insert si uno falla
« en: 10 Abril 2016, 03:31 am »

Tengo un script que sube datos a diferentes tablas mysql y necesito que si un insert falla, no se haga ninguno. Para ello he estado leyendo y creo tener una idea clara:

Código
  1. $mysqli = new mysqli(/* datos de conexión */);
  2. $mysqli->autocommit(FALSE);
  3.  
  4. // el rollback lo dejará todo como estaba aquí
  5. $mysqli->begin_transaction();
  6.  
  7. if ($stmt_uno = $mysqli->prepare('INSERT INTO tabla_principal (uno, dos, tres) VALUES (?, ?, ?)')) {
  8.    $stmt_uno->bind_param('sss', $uno, $dos, $tres);
  9.    $stmt_uno->execute();
  10.  
  11.    $id = (int) $mysqli->insert_id;
  12.  
  13.    if ($stmt_dos = $mysqli->prepare('INSERT INTO sub_tabla (principal_id, cuatro) VALUES (?, ?)')) {
  14.        $stmt_dos->bind_param('is', $id, $cuatro);
  15.        $stmt_dos->execute();
  16.    }
  17.  
  18.    if ($stmt_tres = $mysqli->prepare('INSERT INTO sub_tabla_dos (principal_id, cinco) VALUES (?, ?)')) {
  19.        $stmt_tres->bind_param('is', $id, $cinco);
  20.        $stmt_tres->execute();
  21.    }
  22. }
  23.  
  24.  
  25. if ($mysqli->commit()) {
  26.    // todo correcto, se redirige
  27.    header('Location: /');
  28. } else {
  29.    // algo ha salido mal, se llama rollback
  30.    $mysqli->rollback();
  31.    // y se muestra un mensaje de error
  32. }

Todavía no lo he probado, pero no estoy seguro de si es así o hay que comprobar cada execute()...

¿Alguien puede corregirme?

Gracias!

Edito: cambio la estructura, el resto de inserts dependen del primero, pero si cualquiera falla no debe insertarse nada.


« Última modificación: 12 Abril 2016, 02:35 am por gAb1 » En línea

Gallu

Desconectado Desconectado

Mensajes: 247



Ver Perfil
Re: mysqli rollback todos los insert si uno falla
« Respuesta #1 en: 11 Abril 2016, 11:24 am »

Hola, lo mejor en estos casos es usar bloques try catch.

http://php.net/manual/es/language.exceptions.php

De esta forma te aseguras de que ante cualquier error se ejecute el rollback
Por ejemplo:

Código
  1. $mysqli = new mysqli(/* datos de conexión */);
  2. $mysqli->autocommit(FALSE);
  3.  
  4. // el rollback lo dejará todo como estaba aquí
  5. $mysqli->begin_transaction();
  6.  
  7. try{
  8. if ($stmt_uno = $mysqli->prepare('INSERT INTO tabla_principal (uno, dos, tres) VALUES (?, ?, ?)')) {
  9. $stmt_uno->bind_param('sss', $uno, $dos, $tres);
  10. $stmt_uno->execute();
  11.  
  12. $id = (int) $mysqli->insert_id;
  13.  
  14. if ($stmt_dos = $mysqli->prepare('INSERT INTO sub_tabla (principal_id, cuatro) VALUES (?, ?)')) {
  15. $stmt_dos->bind_param('is', $id, $cuatro);
  16. $stmt_dos->execute();
  17. }
  18.  
  19. if ($stmt_tres = $mysqli->prepare('INSERT INTO sub_tabla_dos (principal_id, cinco) VALUES (?, ?)')) {
  20. $stmt_tres->bind_param('is', $id, $cinco);
  21. $stmt_tres->execute();
  22. }
  23. }
  24.  
  25.  
  26. if ($mysqli->commit()) {
  27. // todo correcto, se redirige
  28. header('Location: /');
  29. }  
  30.  
  31. }catch(Exception $error){
  32.    //deshacemos todo
  33. $mysqli->rollback();
  34. echo 'Excepción capturada: ',  $error->getMessage(), "\n";
  35. }
  36.  


En línea

Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.
gAb1


Desconectado Desconectado

Mensajes: 731


Ver Perfil
Re: mysqli rollback todos los insert si uno falla
« Respuesta #2 en: 12 Abril 2016, 02:35 am »

Ah, al fin algo nuevo. Si que son muy utiles esos blockes. Gracias, dejo como lo he hecho:

Código
  1. $mysqli = new mysqli(/* datos de conexión */);
  2. $mysqli->autocommit(FALSE);
  3.  
  4. // el rollback lo dejará todo como estaba aquí
  5. $mysqli->begin_transaction();
  6.  
  7. try{
  8.  
  9.    if ($stmt_uno = $mysqli->prepare('INSERT INTO tabla_principal (uno, dos, tres) VALUES (?, ?, ?)')) {
  10.        $stmt_uno->bind_param('sss', $uno, $dos, $tres);
  11.  
  12.        if (!$stmt->execute()) {
  13.            throw new Exception($stmt->error);
  14.        }
  15.  
  16.        $id = (int) $mysqli->insert_id;
  17.  
  18.        if ($stmt_dos = $mysqli->prepare('INSERT INTO sub_tabla (principal_id, cuatro) VALUES (?, ?)')) {
  19.            $stmt_dos->bind_param('is', $id, $cuatro);
  20.            if (!$stmt->execute()) {
  21.                throw new Exception($stmt->error);
  22.            }
  23.        }
  24.  
  25.        if ($stmt_tres = $mysqli->prepare('INSERT INTO sub_tabla_dos (principal_id, cinco) VALUES (?, ?)')) {
  26.            $stmt_tres->bind_param('is', $id, $cinco);
  27.            if (!$stmt->execute()) {
  28.                throw new Exception($stmt->error);
  29.            }
  30.        }
  31.    }
  32.  
  33.    if ($mysqli->commit()) {
  34.        $redirect = TRUE;
  35.    } else {
  36.        throw new Exception('Transaction commit failed. Property ID: ' . $id);
  37.    }
  38.  
  39. } catch (Exception $e) {
  40.    try {
  41.        $mysqli->rollback();
  42.        $err_msg = $e->getMessage();
  43.    } catch (Exception $f) {
  44.        $err_msg = $f->getMessage();
  45.    }
  46.    die($usr_msg);
  47. }
  48.  
  49. // es importante volver a activar el autocommit
  50. $mysqli->autocommit(TRUE);

Me costó un buen rato darme cuenta de por qué no se guardaba nada en la db  :-\
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[Solucionado] Problema con bulk insert
Bases de Datos
criskapunk 0 8,541 Último mensaje 16 Junio 2011, 14:59 pm
por criskapunk
[Solucionado] Falla conexión al inicio
GNU/Linux
WifliX 7 5,136 Último mensaje 3 Octubre 2012, 18:53 pm
por Lecter21
SQLite3 INSERT INTO + EXCEPT [SOLUCIONADO]
Bases de Datos
patilanz 4 4,406 Último mensaje 5 Octubre 2015, 21:11 pm
por patilanz
Mysqli error ayuda [ SOLUCIONADO ]
Desarrollo Web
noobcoder 3 3,131 Último mensaje 20 Marzo 2016, 18:46 pm
por noobcoder
[Resuelto] mysqli rollback deja de funcionar en php 7
PHP
gAb1 1 2,991 Último mensaje 8 Junio 2016, 18:22 pm
por gAb1
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines