2011-07-06 7 views
5

Czy można przygotować wiele zapisów przed ich wykonaniem?Przygotuj wiele pozycji przed wykonaniem ich w transakcji?

$db = PDO('..connection info...'); 
$cats_stmt = $db->prepare('SELECT * FROM cats'); 
$dogs_stmt = $db->prepare('SELECT * FROM dogs'); 

$cats_stmt->execute(); 
$cats = $cats_stmt->fetchAll(PDO::FETCH_CLASS);//list of cats 

$dogs_stmt->execute(); 
$dogs = $dogs_stmt->fetchAll(PDO::FETCH_CLASS);//list of dogs 

Przydałoby się to w przypadku pętli, w których dwie instrukcje z różnymi zmiennymi muszą być wykonywane jedna po drugiej. tak:

$stmt_addcat = $db->prepare('INSERT INTO cats (name,age) VALUES(?,?)'); 
$stmt_adddog = $db->prepare('INSERT INTO dogs (name,age) VALUES(?,?)'); 

foreach($cat_n_dog as $bunch){ 
    $db->beginTransaction(); 
    $dog_name = $bunch['dog']['name']; 
    $dog_age = $bunch['dog']['age']; 
    $stmt_adddog->bindParam(1,$dog_name,PDO::PARAM_STR); 
    $stmt_adddog->bindParam(2,$dog_age,PDO::PARAM_STR); 
    $result = $stmt_adddog->execute(); 
    if($result===false){ 
    $db->rollBack(); 
    continue; 
    } 
    $cat_name = $bunch['cat']['name']; 
    $cat_age = $bunch['cat']['age']; 
    $stmt_addcat->bindParam(1,$cat_name,PDO::PARAM_STR); 
    $stmt_addcat->bindParam(2,$cat_age,PDO::PARAM_STR); 
    $result = $stmt_addcat->execute(); 
    if($result===false){ 
    $db->rollBack(); 
    continue; 
    } 
    $db->commit(); 
} 

Pytam bo miałem sytuacje, w których PDO będzie działać buggy i rzucać błędy na sqlite kierowcy, więc zastanawiam się, czy powyższy przykład jest nawet podobno działa.

p.s. przykłady są robione na miejscu.

+0

Dlaczego nie spróbować? –

+2

Całkiem dobrze jest używać PDO w sposób, jaki opisujesz. Jedyny problem polega na tym, że używasz 'beginTransaction()' w swoim oświadczeniu foreach, które pokonuje cel transakcji, ale nie wiem, czy to błąd popełniony podczas pisania tego przykładu, czy też jest to coś, czego faktycznie używasz. –

+0

błędy porzucone przez sterownik pdo sqlite –

Odpowiedz

6

Będę publikować jako odpowiedź, ponieważ komentarze nie pozwalają na wystarczającą ilość miejsca.

Tak, możesz przygotować kilka przygotowanych wyciągów, a następnie wykonać je w pętli, nie ma w tym nic złego.

Część transakcji jest niepoprawna. Jeśli chcesz wykonać wszystkie zapytania lub nie, musisz rozpocząć transakcję poza pętlą (to samo z zatwierdzeniem). Tutaj przydaje się PHP try/catch.

$db = PDO('..connection info...'); 

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Set error mode to exceptions 

try 
{ 
    $stmt_addcat = $db->prepare('INSERT INTO cats (name,age) VALUES(?,?)'); 
    $stmt_adddog = $db->prepare('INSERT INTO dogs (name,age) VALUES(?,?)'); 

    $db->beginTransaction(); 

    foreach($cat_n_dog as $bunch) { } // Do your foreach binding and executing here 

    $db->commit(); 
} 
catch(PDOException $e) 
{ 
    $db->rollBack(); 

    echo "Error occurred. Error message: ". $e->getMessage() .". File: ". $e->getFile() .". Line: ". $e->getLine(); 
} 
+0

Myślałem, że każda transakcja "grupuje" zapytania, więc wstawienie każdej pary kotów do transakcji w pętli umożliwi kontynuację lub niepowodzenie pętli w jednej parze zapytań. p.s. czy Twoje foreach obejmuje rollback? –

+0

Wykonasz 1 zapytanie o kota i 1 zapytanie o psa w sposób, w jaki skonstruowałeś transakcję. Punkt transakcji jest całkowity lub żaden, dlaczego zgrupowałbyś je 2 na 2? Zapomniałem wycofywania w moim przykładzie, zredagowałem to, aby było jaśniej. –

+0

Tak, rollback w twoim przykładzie pomógł, dziękuję. –

-1

prostu chciał komentować tutaj, że kiedy umieszczony kod podany przez Michael J.V. w moim projekcie miałem uśmiech na mojej twarzy, że nie udało się usunąć.

Ten kod z ChNP jest tak piękny. Właśnie przygotowałem i wykonałem ponad 500 zapytań z wycofywaniem ... JAK ELEGANCKI!

Dla nieco więcej wyjaśnień wewnątrz pętli foreach ... Twój kod powinien wyglądać simmilar do

$stmt = $db->prepare($query); 
$stmt->execute(array('name', 'age')); 
+0

W rzeczywistości przygotowujesz go poza pętlą foreach, i tylko raz dla każdego typu zapytania, pętla musi zawierać tylko wywołania '$ stmt-> execute (...)'. Mam nadzieję, że dzięki temu Twój uśmiech będzie jeszcze większy :) –

Powiązane problemy