PDO mysql: Comment savoir si l'insertion a réussi


96

J'utilise PDO pour insérer un enregistrement (mysql et php)

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

Existe-t-il un moyen de savoir s'il a été inséré avec succès, par exemple si l'enregistrement n'a pas été inséré parce qu'il s'agissait d'un doublon?

Edit: bien sûr, je peux consulter la base de données, mais je veux dire des commentaires programmatiques.

Réponses:


140

PDOStatement->execute()retourne vrai en cas de succès. Il y a aussi PDOStatement->errorCode()que vous pouvez vérifier les erreurs.


1
Comment regardez-vous la valeur de execute ()?
Mallow

29
Pas plus comme ça, $ value = $ stmt-> execute (); if ($ value) {// true} else {// false}
Ólafur Waage

23
Ou vous pouvez simplement le faireif ($stmt->execute()) { //true }
Gavin

2
Est-ce que PDOStatement->execute()et PDOStatement->errorCode()totalement cohérent les uns avec les autres? Y a-t-il des circonstances où PDOStatement->errorCode()a quelque chose mais PDOStatement->execute()renvoie vrai? Ou quand PDOStatement->execute()retourne faux mais PDOStatement->errorCode()n'a rien?
datasn.io

1
Mais INSERT IGNORE retournerait également vrai même si aucun nouvel enregistrement n'était inséré
Koffeehaus

24

Étant donné que le mode d'erreur le plus recommandé pour PDO est ERRMODE_EXCEPTION, aucune execute()vérification directe des résultats ne fonctionnera jamais . Comme l'exécution du code n'atteindra même pas la condition proposée dans d'autres réponses.

Il existe donc trois scénarios possibles pour gérer le résultat de l'exécution de la requête dans PDO:

  1. Pour dire le succès, aucune vérification n'est nécessaire. Continuez simplement avec le déroulement de votre programme.
  2. Pour gérer l'erreur inattendue, continuez avec la même chose - aucun code de traitement immédiat n'est nécessaire. Une exception sera levée en cas d'erreur de base de données, et elle remontera jusqu'au gestionnaire d'erreurs à l'échelle du site qui aboutira finalement à une page d'erreur 500 commune.
  3. Pour gérer l'erreur attendue, comme une clé primaire en double, et si vous disposez d'un certain scénario pour gérer cette erreur particulière, utilisez un try..catchopérateur.

Pour un utilisateur PHP régulier, cela semble un peu étranger - comment faire, ne pas vérifier le résultat direct de l'opération? - mais c'est exactement ainsi que fonctionnent les exceptions - vous vérifiez l'erreur ailleurs. Une fois pour toute. Extrêmement pratique.

Donc, en un mot: dans un code normal, vous n'avez pas du tout besoin de gestion des erreurs. Gardez simplement votre code tel quel:

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

En cas de succès, il vous le dira, en cas d'erreur, il vous montrera la page d'erreur habituelle que votre application affiche pour une telle occasion.

Seulement dans le cas où vous avez un scénario de gestion autre que simplement signaler l'erreur, mettez votre instruction d'insertion dans un try..catchopérateur, vérifiez s'il s'agit de l'erreur que vous attendiez et gérez-la; ou - si l'erreur était différente - relancez l'exception, pour qu'elle puisse être gérée par le gestionnaire d'erreurs à l'échelle du site de la manière habituelle. Voici l'exemple de code de mon article sur la gestion des erreurs avec 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!";

Dans le code ci-dessus, nous vérifions l'erreur particulière pour prendre des mesures et relançons l'exception pour toute autre erreur (aucune table de ce type par exemple) qui sera signalée à un programmeur.

Encore une fois - juste pour dire à un utilisateur quelque chose comme "Votre insertion a réussi", aucune condition n'est jamais nécessaire.


Quelle est la signification de «succès»? Est-ce que cela signifie qu'une nouvelle ligne est insérée, ou cela signifie qu'il n'y a pas d'erreur?
Martin AJ

Pour la requête INSERT, c'est à peu près la même chose.
Your Common Sense

Vous avez raison. Pouvez-vous me dire ce qu'il en est de la query()fonction? Puis-je utiliser try-catch pour query()au lieu de prepared()->execute()?
Martin AJ

3
Vous ne devez jamais utiliser query () pour les insertions en premier lieu. Insert signifie qu'il y a une entrée et inpout signifie qu'il doit être préparé.
Your Common Sense

1
En utilisant MySQL, j'ai dû vérifier si $ e-> errorInfo [1] == 1062 pour vérifier que l'insertion a échoué, car $ e-> getCode () est toujours 23000.
tronman


9

Si une requête de mise à jour s'exécute avec des valeurs qui correspondent à l'enregistrement de base de données actuel, elle $stmt->rowCount()sera renvoyée 0car aucune ligne n'a été affectée. Si vous avez un if( rowCount() == 1 )test de réussite, vous penserez que la mise à jour a échoué alors qu'elle n'a pas échoué mais que les valeurs étaient déjà dans la base de données, donc rien ne change.

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

Cela n'a pas fonctionné pour moi lorsque j'ai essayé de mettre à jour un enregistrement avec un champ de clé unique qui a été violé. La requête a renvoyé le succès mais une autre requête renvoie l'ancienne valeur de champ.


3
Si vous avez BESOIN que l'enregistrement soit inséré, le meilleur moyen est de vérifier comme ceci ............................. ..... .................. if($stmt->execute() && ($stmt->rowCount()>0))
jave.web

4

Vous pouvez tester le nombre de lignes

    $sqlStatement->execute( ...);
    if ($sqlStatement->rowCount() > 0)
    {
        return true;
    }

Une référence à la documentation est toujours utile @YourCommonSense. Il dit que "ce comportement n'est pas garanti pour toutes les bases de données et ne doit pas être invoqué pour les applications portables." Mais se limite à sélectionner d'une part, et d'autre part pris en charge pour mysql, qui fait l'objet de cet article.
crafter

tapez simplement "pdo rowcount" dans la barre d'adresse de votre navigateur et cliquez sur le premier lien. il faut moins de frappe qu'un commentaire
Votre bon sens

1
@crafter Correct. Il dit que rowCount () peut être impossible à résoudre pour les SELECTrequêtes (et même là, la documentation parle de plusieurs requêtes). Il ne dit rien sur DELETE, INSERTou UPDATE, ce qui semble bien fonctionner (la question portait sur une INSERTrequête). Cependant, je suis nouveau sur PDO et si je me trompe et que quelqu'un a d'autres références, veuillez les écrire ici. Je suis intéressé de voir s'il y a de réels inconvénients pour les 3 commandes ci-dessus.
StanE

1

Utiliser l'ID comme clé primaire avec incrémentation automatique

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

id incrémental est toujours plus grand que zéro même sur le premier enregistrement, ce qui signifie qu'il retournera toujours une valeur vraie pour id coz plus grand que zéro signifie vrai en PHP

if ($insertid)
   echo "record inserted successfully";
else
   echo "record insertion failed";

Que faire si je n'ai pas besoin d'un champ incrémenté automatiquement dans ma table?
Votre bon sens

Qui dun? tu? avec l'API RESTFul qui est si largement utilisée, l'identifiant d'incrémentation automatique est comme obligatoire.
cavalier rbk

Pourquoi quelqu'un n'aurait-il pas d'incrémentation primaire et automatique ou toute autre colonne de séquence? Si une méthode de vérification est nécessaire, ajoutez une colonne séquentielle. Si cette solution n'est pas pour vous ne l'ajoutez pas. C'est très bien pour moi, j'utilise toujours une colonne séquentielle et auto-incrémentée, donc j'ai toujours un moyen de tester si ma requête a réussi.
Samuel Ramzan le

0

PDOStatement-> execute () peut lever une exception

alors ce que tu peux faire c'est

try
{
PDOStatement->execute();
//record inserted
}
catch(Exception $e)
{
//Some error occured. (i.e. violation of constraints)
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.