PDO mysql: come sapere se l'inserimento è andato a buon fine


96

Sto usando PDO per inserire un record (mysql e php)

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

C'è un modo per sapere se è stato inserito correttamente, ad esempio se il record non è stato inserito perché era un duplicato?

Modifica: ovviamente posso guardare il database, ma intendo feedback programmatico.

Risposte:


140

PDOStatement->execute()restituisce vero in caso di successo. C'è anche quello PDOStatement->errorCode()che puoi controllare per errori.


1
Come guardi il valore execute ()?
Mallow

29
Non più così, $ value = $ stmt-> execute (); if ($ value) {// true} else {// false}
Ólafur Waage

23
Oppure puoi semplicemente fareif ($stmt->execute()) { //true }
Gavin

2
E ' PDOStatement->execute()e PDOStatement->errorCode()del tutto coerente con l'altro? Ci sono circostanze in cui PDOStatement->errorCode()ha qualcosa ma PDOStatement->execute()restituisce vero? O quando PDOStatement->execute()ritorna falso ma PDOStatement->errorCode()non ha niente?
datasn.io

1
Ma INSERT IGNORE tornerebbe vero anche se non fosse stato inserito nessun nuovo record
Koffeehaus

24

Dato che la modalità di errore più consigliata per PDO è ERRMODE_EXCEPTION, nessuna execute()verifica diretta dei risultati funzionerà mai . Poiché l'esecuzione del codice non raggiungerà nemmeno la condizione offerta in altre risposte.

Quindi, ci sono tre possibili scenari per gestire il risultato dell'esecuzione della query in PDO:

  1. Per raccontare il successo, non è necessaria alcuna verifica. Continua con il flusso del tuo programma.
  2. Per gestire l'errore imprevisto, mantieni lo stesso: non è necessario alcun codice di gestione immediata. Verrà generata un'eccezione in caso di errore del database e verrà visualizzata in bolla fino al gestore degli errori a livello di sito che alla fine si tradurrà in una pagina di errore 500 comune.
  3. Per gestire l'errore previsto, come una chiave primaria duplicata, e se hai un determinato scenario per gestire questo particolare errore, utilizza un try..catchoperatore.

Per un normale utente PHP suona un po 'estraneo - che ne dici, non per verificare il risultato diretto dell'operazione? - ma questo è esattamente il modo in cui funzionano le eccezioni: controlli l'errore da qualche altra parte. Una volta per tutte. Estremamente conveniente.

Quindi, in poche parole: in un codice normale non è necessaria alcuna gestione degli errori. Mantieni il tuo codice così com'è:

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

In caso di successo te lo dirà, in caso di errore ti mostrerà la normale pagina di errore che la tua applicazione sta mostrando per tale occasione.

Solo nel caso in cui tu abbia uno scenario di gestione diverso dalla semplice segnalazione dell'errore, metti la tua istruzione insert in un try..catchoperatore, controlla se era l'errore che ti aspettavi e gestiscilo; oppure - se l'errore fosse diverso - rilanciare l'eccezione, per rendere possibile essere gestito dal gestore degli errori a livello di sito nel modo usuale. Di seguito è riportato il codice di esempio dal mio articolo sulla gestione degli errori 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!";

Nel codice sopra stiamo controllando che l'errore particolare intraprenda un'azione e rilanciamo l'eccezione per qualsiasi altro errore (nessuna tabella di questo tipo, ad esempio) che verrà segnalato a un programmatore.

Mentre di nuovo - solo per dire a un utente qualcosa come "Il tuo inserimento è andato a buon fine" non è mai necessaria alcuna condizione.


Qual è il significato di "successo"? Significa che è stata inserita una nuova riga o che non ci sono errori?
Martin AJ

Per la query INSERT è più o meno lo stesso.
Il tuo buon senso

Hai ragione .. Potresti per favore dirmi che mi dici della query()funzione? Posso usare try-catch per query()invece di prepared()->execute()?
Martin AJ

3
Non dovresti mai usare query () per gli inserti in primo luogo. Inserisci significa che c'è un input e inpout significa che dovrebbe essere preparato.
Il tuo buon senso

1
Utilizzando MySQL, ho dovuto controllare se $ e-> errorInfo [1] == 1062 per verificare che l'inserimento non fosse riuscito, perché $ e-> getCode () è sempre 23000.
tronman


9

Se una query di aggiornamento viene eseguita con valori che corrispondono al record del database corrente, $stmt->rowCount()verrà restituito 0per nessuna riga interessata. Se devi if( rowCount() == 1 )testare il successo, penserai che l'aggiornamento non sia riuscito quando non ha avuto esito negativo ma i valori erano già nel database, quindi non cambia nulla.

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

Questo non ha funzionato per me quando ho provato ad aggiornare un record con un campo chiave univoco che è stato violato. La query ha restituito successo ma un'altra query restituisce il vecchio valore del campo.


3
Se è NECESSARIO che il record sia inserito, il modo migliore è controllare in questo modo ............................. ..... .................. if($stmt->execute() && ($stmt->rowCount()>0))
jave.web

4

Puoi testare il conteggio delle righe

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

Un riferimento alla documentazione è sempre utile @YourCommonSense. Dice "questo comportamento non è garantito per tutti i database e non dovrebbe essere invocato per le applicazioni portatili." Ma è limitato a selezionare in primo luogo e in secondo luogo supportato per mysql, che è l'argomento di questo post.
crafter

basta digitare "pdo rowcount" nella barra degli indirizzi del browser e fare clic sul primo collegamento. ci vuole meno battitura di un commento
Il tuo buon senso

1
@crafter corretto. Dice che rowCount () può essere inaffidabile per le SELECTquery (e anche lì, i documenti parlano di più query). Non dice nulla su DELETE, INSERTo UPDATE, che sembra funzionare bene (la domanda riguardava una INSERTquery). Tuttavia, sono nuovo a PDO e se mi sbaglio e qualcuno ha altre referenze, scrivile qui. Sono interessato a vedere se ci sono degli svantaggi reali per i 3 comandi sopra.
StanE

1

Usa id come chiave primaria con incremento automatico

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

l'id incrementale è sempre maggiore di zero anche sul primo record, quindi significa che restituirà sempre un valore vero per id perché maggiore di zero significa vero in PHP

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

Cosa succede se non ho bisogno di un campo incrementato automaticamente nella mia tabella?
Il tuo buon senso

Chi dun? tu? con l'API RESTFul che viene utilizzata così ampiamente, l'id di incremento automatico è come obbligatorio.
jumper rbk

Perché qualcuno non dovrebbe avere un incremento principale e automatico o qualsiasi altra colonna di sequenza? Se è necessario un metodo di verifica, aggiungere una colonna sequenziale. Se questa soluzione non fa per te non aggiungerla. Per me va bene, uso sempre una colonna sequenziale e con incremento automatico, quindi ho sempre un modo per verificare se la mia query ha avuto successo.
Samuel Ramzan,

0

PDOStatement-> execute () può generare un'eccezione

quindi quello che puoi fare è

try
{
PDOStatement->execute();
//record inserted
}
catch(Exception $e)
{
//Some error occured. (i.e. violation of constraints)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.