PDO mysql: cómo saber si la inserción fue exitosa

96

Estoy usando PDO para insertar un registro (mysql y php)

$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();

¿Hay alguna forma de saber si se insertó correctamente, por ejemplo, si el registro no se insertó porque era un duplicado?

Editar: por supuesto que puedo mirar la base de datos, pero me refiero a comentarios programáticos.

Chris
fuente

Respuestas:

140

PDOStatement->execute()devuelve verdadero en caso de éxito. También existe el PDOStatement->errorCode()que puede verificar si hay errores.

Ólafur Waage
fuente
1
¿Cómo miras el valor de ejecutar ()?
Mallow
29
No más como esto, $ value = $ stmt-> execute (); if ($ value) {// true} else {// false}
Ólafur Waage
23
O simplemente puede hacerloif ($stmt->execute()) { //true }
Gavin
2
¿Son PDOStatement->execute()y PDOStatement->errorCode()totalmente coherentes entre sí? ¿Hay alguna circunstancia en la que PDOStatement->errorCode()haya algo pero PDOStatement->execute()devuelva verdadero? ¿O cuando PDOStatement->execute()devuelve falso pero PDOStatement->errorCode()no tiene nada?
datasn.io
1
Pero INSERT IGNORE también devolvería verdadero incluso si no se insertó un nuevo registro
Koffeehaus
24

Dado que el modo de error más recomendado para PDO es ERRMODE_EXCEPTION, nunca funcionará la verificación directa de execute()resultados . Como la ejecución del código ni siquiera alcanzará la condición ofrecida en otras respuestas.

Por lo tanto, hay tres escenarios posibles para manejar el resultado de la ejecución de la consulta en PDO:

  1. Para contar el éxito, no se necesita verificación. Siga con el flujo de su programa.
  2. Para manejar el error inesperado, siga igual: no se necesita un código de manejo inmediato. Se lanzará una excepción en caso de un error de la base de datos, y aparecerá en el controlador de errores de todo el sitio que eventualmente resultará en una página de error 500 común.
  3. Para manejar el error esperado, como una clave primaria duplicada, y si tiene un escenario determinado para manejar este error en particular, utilice un try..catchoperador.

Para un usuario habitual de PHP, suena un poco extraño, ¿cómo es eso, no verificar el resultado directo de la operación? - pero así es exactamente como funcionan las excepciones: verifica el error en otro lugar. De una vez por todas. Extremadamente conveniente.

Entonces, en pocas palabras: en un código normal, no necesita ningún manejo de errores en absoluto. Simplemente mantenga su código como está:

$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();
echo "Success!"; // whatever

En caso de éxito, se lo dirá, en caso de error, le mostrará la página de error habitual que muestra su aplicación para tal ocasión.

Solo en caso de que tenga un escenario de manejo que no sea simplemente informar el error, coloque su declaración de inserción en un try..catchoperador, verifique si fue el error que esperaba y maneje; o, si el error fue diferente, vuelva a lanzar la excepción, para que sea posible que la maneje el controlador de errores en todo el sitio de la manera habitual. A continuación se muestra el código de ejemplo de mi artículo sobre el manejo de errores con PDO :

try {
     $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data);
} catch (PDOException $e) {
    if ($e->getCode() == 1062) {
        // Take some action if there is a key constraint violation, i.e. duplicate name
    } else {
        throw $e;
    }
}
echo "Success!";

En el código anterior, estamos verificando el error en particular para tomar alguna acción y volviendo a lanzar la excepción para cualquier otro error (no hay tal tabla, por ejemplo) que se informará a un programador.

Una vez más, solo para decirle a un usuario algo como "Su inserción fue exitosa" , nunca se necesita ninguna condición.

Tu sentido común
fuente
¿Cuál es el significado de "éxito"? ¿Eso significa que se insertó una nueva fila, o eso significa que no hay ningún error?
Martin AJ
Para la consulta INSERT es más o menos lo mismo.
Tu sentido común
Tiene razón ... ¿Podría decirme qué hay de la query()función? ¿Puedo usar try-catch para en query()lugar de prepared()->execute()?
Martin AJ
3
En primer lugar, nunca debe usar query () para inserciones. Insertar significa que hay entrada y entrada significa que debe estar preparado.
Tu sentido común
1
Usando MySQL, tuve que verificar si $ e-> errorInfo [1] == 1062 para verificar que la inserción falló, porque $ e-> getCode () siempre es 23000.
tronman
9

Intente observar el valor de retorno de execute, que está TRUEen el éxito y FALSEen el fracaso.

Dominic Rodger
fuente
9

Si una consulta de actualización se ejecuta con valores que coinciden con el registro de la base de datos actual, entonces $stmt->rowCount()regresará 0porque ninguna fila se vio afectada. Si tiene una if( rowCount() == 1 )prueba de éxito, pensará que la actualización falló cuando no falló, pero los valores ya estaban en la base de datos, por lo que nada cambia.

$stmt->execute();
if( $stmt ) return "success";

Esto no funcionó para mí cuando intenté actualizar un registro con un campo de clave único que fue violado. La consulta devolvió el éxito, pero otra consulta devuelve el valor del campo anterior.

dan
fuente
3
Si NECESITA que se inserte el registro, la mejor manera es verificarlo así ............................. ..... .................. if($stmt->execute() && ($stmt->rowCount()>0))
jave.web
4

Puedes probar el recuento de filas

    $sqlStatement->execute( ...);
    if ($sqlStatement->rowCount() > 0)
    {
        return true;
    }
artesano
fuente
Una referencia a los documentos siempre es útil @YourCommonSense. Dice "este comportamiento no está garantizado para todas las bases de datos y no debe confiarse en él para aplicaciones portátiles", pero se limita a seleccionar en primer lugar y, en segundo lugar, es compatible con mysql, que es el tema de esta publicación.
crafter
simplemente escriba "pdo rowcount" en la barra de direcciones de su navegador y haga clic en el primer enlace. se necesita menos escribir que un comentario
su sentido común
1
@crafter Correcto. Dice que rowCount () puede ser inviable para las SELECTconsultas (e incluso allí, los documentos hablan de varias consultas). No dice nada sobre DELETE, INSERTo UPDATE, que parecen funcionar bien (la pregunta era sobre una INSERTconsulta). Sin embargo, soy nuevo en PDO y si me equivoco y alguien tiene otras referencias, escríbalas aquí. Estoy interesado en ver si existen desventajas reales para los 3 comandos anteriores.
StanE
1

Utilice la identificación como clave principal con incremento automático

$stmt->execute();
$insertid = $conn->lastInsertId();

La identificación incremental siempre es mayor que cero incluso en el primer registro, por lo que significa que siempre devolverá un valor verdadero para la identificación porque mayor que cero significa verdadero en PHP

if ($insertid)
   echo "record inserted successfully";
else
   echo "record insertion failed";
puente rbk
fuente
¿Qué pasa si no necesito un campo incrementado automáticamente en mi tabla?
Tu sentido común
¿Quién dun? ¿tú? con la API RESTFul que se está utilizando tan ampliamente, el ID de incremento automático es como obligatorio.
jumper rbk
¿Por qué alguien no tendría un incremento primario y automático o cualquier otra columna de secuencia? Si se necesita un método de verificación, agregue cualquier columna secuencial. Si esta solución no es para usted, no la agregue. Es bueno para mí, siempre uso alguna columna secuencial y de incremento automático, por lo que siempre tengo una manera de probar si mi consulta fue exitosa.
Samuel Ramzan
0

PDOStatement-> execute () puede lanzar una excepción

entonces lo que puedes hacer es

try
{
PDOStatement->execute();
//record inserted
}
catch(Exception $e)
{
//Some error occured. (i.e. violation of constraints)
}
Sumit P Makwana
fuente