PDO mysql: Como saber se a inserção foi bem-sucedida

96

Estou usando PDO para inserir um registro (mysql e php)

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

Existe uma maneira de saber se ele foi inserido com sucesso, por exemplo, se o registro não foi inserido porque era uma duplicata?

Editar: é claro que posso olhar o banco de dados, mas quero dizer feedback programático.

Chris
fonte

Respostas:

140

PDOStatement->execute()retorna verdadeiro em caso de sucesso. Também é PDOStatement->errorCode()possível verificar se há erros.

Ólafur Waage
fonte
1
Como você vê o valor execute ()?
Mallow
29
Nada mais parecido com isso, $ value = $ stmt-> execute (); if ($ value) {// true} else {// false}
Ólafur Waage
23
Ou você pode apenas fazerif ($stmt->execute()) { //true }
Gavin
2
São PDOStatement->execute()e PDOStatement->errorCode()totalmente consistentes um com o outro? Existe alguma circunstância em que PDOStatement->errorCode()tem algo mas PDOStatement->execute()retorna verdadeiro? Ou quando PDOStatement->execute()retorna falso mas PDOStatement->errorCode()não tem nada?
datasn.io
1
Mas INSERT IGNORE também retornaria verdadeiro mesmo se nenhum novo registro fosse inserido
Koffeehaus
24

Dado que o modo de erro mais recomendado para PDO é ERRMODE_EXCEPTION, nenhuma execute()verificação de resultado direto funcionará . Pois a execução do código nem atingirá a condição oferecida nas outras respostas.

Portanto, existem três cenários possíveis para lidar com o resultado da execução da consulta no PDO:

  1. Para saber o sucesso, nenhuma verificação é necessária. Apenas continue com o fluxo do programa.
  2. Para lidar com o erro inesperado, continue com o mesmo - nenhum código de tratamento imediato é necessário. Uma exceção será lançada no caso de um erro de banco de dados e aparecerá no manipulador de erros de todo o site que eventualmente resultará em uma página de erro 500 comum.
  3. Para lidar com o erro esperado, como uma chave primária duplicada, e se você tiver um determinado cenário para lidar com esse erro específico, use um try..catchoperador.

Para um usuário normal de PHP, parece um pouco estranho - que tal não verificar o resultado direto da operação? - mas é exatamente assim que as exceções funcionam - você verifica o erro em outro lugar. De uma vez por todas. Extremamente conveniente.

Então, em poucas palavras: em um código normal, você não precisa de nenhum tratamento de erros. Basta manter seu código como está:

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

Em caso de sucesso, ele dirá a você, em caso de erro, ele mostrará a página de erro normal que seu aplicativo está mostrando para tal ocasião.

Apenas no caso de você ter um cenário de tratamento diferente de apenas relatar o erro, coloque sua instrução insert em um try..catchoperador, verifique se foi o erro que você esperava e trate-o; ou - se o erro for diferente - relançar a exceção, para possibilitar que seja tratada pela maneira usual de tratamento de erros em todo o site. Abaixo está o código de exemplo do meu artigo sobre tratamento de erros com 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!";

No código acima, estamos verificando o erro específico para realizar alguma ação e lançando novamente a exceção para qualquer outro erro (nenhuma tabela, por exemplo) que será relatado a um programador.

Mais uma vez - apenas para dizer ao usuário algo como "Sua inserção foi bem-sucedida", nenhuma condição é necessária.

Seu senso comum
fonte
Qual é o significado de "sucesso"? Isso significa que uma nova linha foi inserida ou que não há nenhum erro?
Martin AJ
Para a consulta INSERT, é praticamente o mesmo.
Seu senso comum
Você está certo .. Só pode me dizer o que acontece com a query()função? Posso usar try-catch para em query()vez de prepared()->execute()?
Martin AJ
3
Você nunca deve usar query () para inserções em primeiro lugar. Inserir significa que há entrada e entrada significa que deve ser preparado.
Seu senso comum
1
Usando MySQL, tive que verificar se $ e-> errorInfo [1] == 1062 para verificar se a inserção falhou, porque $ e-> getCode () é sempre 23000.
tronman
9

Tente observar o valor de retorno de execute, que está TRUEno sucesso e FALSEno fracasso.

Dominic Rodger
fonte
9

Se uma consulta de atualização for executada com valores que correspondem ao registro do banco de dados atual, $stmt->rowCount()ela retornará 0para nenhuma linha afetada. Se você tiver um if( rowCount() == 1 )teste para testar o sucesso, pensará que a atualização falhou quando não falhou, mas os valores já estavam no banco de dados, então nada mudou.

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

Isso não funcionou para mim quando tentei atualizar um registro com um campo de chave exclusivo que foi violado. A consulta retornou sucesso, mas outra consulta retorna o valor do campo antigo.

dan
fonte
3
Se você PRECISA que o registro seja inserido, a melhor maneira é verificar assim ............................. ..... .................. if($stmt->execute() && ($stmt->rowCount()>0))
jave.web
4

Você pode testar o número de linhas

    $sqlStatement->execute( ...);
    if ($sqlStatement->rowCount() > 0)
    {
        return true;
    }
construtor
fonte
Uma referência aos documentos é sempre útil @YourCommonSense. Ele diz que "este comportamento não é garantido para todos os bancos de dados e não deve ser considerado para aplicativos portáteis." Mas é limitado a selecionar primeiro, e em segundo lugar, é compatível com mysql, que é o assunto deste post.
crafter
basta digitar "pdo rowcount" na barra de endereços do navegador e clicar no primeiro link. leva menos digitação do que um comentário
Seu senso comum,
1
@crafter Correto. Ele diz que rowCount () pode não ser confiável para SELECTconsultas (e mesmo lá, a documentação fala sobre múltiplas consultas). Não diz nada sobre DELETE, INSERTou UPDATE, o que parece ser bom para o trabalho (a pergunta foi sobre uma INSERTconsulta). No entanto, sou novo no PDO e se eu estiver errado e alguém tiver outras referências, por favor, escreva-as aqui. Estou interessado em ver se existem desvantagens reais para os 3 comandos acima.
StanE
1

Use id como chave primária com incremento automático

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

id incremental é sempre maior que zero mesmo no primeiro registro, então isso significa que sempre retornará um valor verdadeiro para id porque maior que zero significa verdadeiro em PHP

if ($insertid)
   echo "record inserted successfully";
else
   echo "record insertion failed";
jumper rbk
fonte
E se eu não precisar de um campo incrementado automaticamente em minha tabela?
Seu senso comum
Quem dun? vocês? com a API RESTFul que está sendo usada tão amplamente, o ID de incremento automático é quase obrigatório.
jumper rbk
Por que alguém não teria um incremento primário e automático ou qualquer outra coluna de sequência? Se o método de verificação for necessário, adicione qualquer coluna sequencial. Se esta solução não for para Você, não a adicione. É uma boa para mim, sempre uso alguma coluna sequencial e de incremento automático, então sempre tenho uma maneira de testar se minha consulta foi bem-sucedida.
Samuel Ramzan
0

PDOStatement-> execute () pode lançar uma exceção

então o que você pode fazer é

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