JorgitoDF 0 Denunciar post Postado Abril 6, 2014 Boa noite pessoal, sou iniciante em PDO em PHP e estou com uma dificuldade em transações, gostaria de saber se alguém pode me ajudar neste ponto abaixo: Quero colocar vários INSERT num único bloco de transação pois caso ocorra algum erro na gravação de alguma tabela todos os INSERT devem ser cancelados (rollback). Segue o meu código: <?php header("Content-Type: text/html; charset=UTF-8",true); include("bd/conexao_pdo.php"); $banco = conectar(); $txtUf = $_POST['idUf']; $txtCidade = mb_strtoupper($_POST['idCidade']); $txtBairro = mb_strtoupper($_POST['idBairro']); $sql = 'INSERT INTO tb_cidade (cid_nome, fk_id_uf_tb_cidade) VALUES (:cidade, :fk_uf)'; $sql1 = 'INSERT INTO tb_bairro (bai_nome, fk_id_cidade_tb_bairro) VALUES (:bairro, :fk_cidade)'; $banco->beginTransaction(); $create_cid = $banco->prepare($sql); $create_cid->bindValue(':cidade', $txtCidade, PDO::PARAM_STR); $create_cid->bindValue(':fk_uf', $txtUf, PDO::PARAM_INT); $create_cidade = $create_cid->execute(); if (!$create_cidade) { $banco->rollBack(); die("Erro ao gravar Cidade"); } else { $idCidade = $banco->lastInsertId(); $banco->commit(); } $banco->beginTransaction(); $create_bai = $banco->prepare($sql1); $create_bai->bindValue(':bairro', $txtBairro, PDO::PARAM_STR); $create_bai->bindValue(':fk_cidade', $idCidade, PDO::PARAM_INT); $create_bairro = $create_bai->execute(); if (!$create_bairro) { $banco->rollBack(); die("Erro ao gravar Bairro"); } else { $idBairro = $banco->lastInsertId(); $banco->commit(); echo "Dados gravados com sucesso..."; } ?> Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Abril 7, 2014 Se você quiser que todos os inserts sejam revertidos em caso de erro, utilize apenas uma transaction e exceptions para tratar os erros dos inserts. try { $banco->setAttribute(PDO::ATTR_ERRMODE , PDO::ERRMODE_EXCEPTION);//Ativa o lançamento de exceptions para erros $banco->beginTransaction(); $create_cid = $banco->prepare($sql); $create_cid->bindValue(':cidade', $txtCidade, PDO::PARAM_STR); $create_cid->bindValue(':fk_uf', $txtUf, PDO::PARAM_INT); $create_cid->execute();//Não há necessidade em verificar o retorno, se não inserir, será lançada uma exception $create_bai = $banco->prepare($sql1); $create_bai->bindValue(':bairro', $txtBairro, PDO::PARAM_STR); $create_bai->bindValue(':fk_cidade', $idCidade, PDO::PARAM_INT); $create_bai->execute();//Não há necessidade em verificar o retorno, se não inserir, será lançada uma exception $banco->commit(); } catch (PDOException $exception) { $banco->rollback(); printf('Não foi possível realizar a operação: %s' , $exception); } Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Abril 7, 2014 Em uma pesquisa no que fiz, no php 5.5 + da para ver quais inserts falharam no bloco finally try{ // } catch (PDOException $exception) { $banco->rollback(); printf('Não foi possível realizar a operação: %s' , $exception); } finally { // echo erro na sql tal } Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Abril 7, 2014 Não se esqueça de adicionar $banco->setAttribute(PDO::ATTR_AUTOCOMMIT, false); ANTES de iniciar a transação Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Abril 7, 2014 Não se esqueça de adicionar $banco->setAttribute(PDO::ATTR_AUTOCOMMIT, false); ANTES de iniciar a transação Não há essa necessidade, beginTransaction automaticamente seta auto commit como false. Compartilhar este post Link para o post Compartilhar em outros sites
JorgitoDF 0 Denunciar post Postado Abril 7, 2014 Valeu mesmo Williams Duarte pelas dicas, fiz aqui e deu tudo certo, muito obrigado mesmo. Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Abril 7, 2014 Há um porém em utilizar o bloco finally para tratar as sqls que deram errado, pois o finally é sempre executado, mesmo que nenhum erro aconteça. Logo, se é um tratamento específico de erros das queries, esse tratamento deve ser feito no catch. Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Abril 7, 2014 #6 Quem te ajudou foi o Gabriel Heming :grin: Há um porém em utilizar o bloco finally para tratar as sqls que deram errado, pois o finally é sempre executado, mesmo que nenhum erro aconteça. Logo, se é um tratamento específico de erros das queries, esse tratamento deve ser feito no catch. Sei!!! Mas era uma forma diferente, vi em um post em um fórum gringo, não me recordo a url, mas era uma forma diferente, pega o erro do catch e disparava um email dentro do finally, bem interessante, mas aqui para mim já não rola 5.4 Compartilhar este post Link para o post Compartilhar em outros sites
JorgitoDF 0 Denunciar post Postado Abril 7, 2014 Sim o Gabriel Heming também! :) Compartilhar este post Link para o post Compartilhar em outros sites