2015-09-16 7 views
9

Mam dziwny problem z PDO, który nie rzuca wyjątku po wstawieniu powielonej wartości. W tym przypadku oczekiwałem błędu.PHP PDO nie wyrzuca wyjątku po duplikacie wstawienia klucza

Odpowiedni kod:

try 
{ 
    $db_conn = new PDO("mysql:host=".$config["database"]["hostname"].";charset=utf8", $config["database"]["username"], $config["database"]["password"], []); 
    $db_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $db_conn->exec(file_get_contents("some_file_with_data.sql"); 
} 
catch(Exception $e) 
{ 
    // PDOException extends RuntimeException extends Exception so exceptions should be catched here 
    // however for the duplicate key entry it will not throw an exception 
} 

Plik z danymi SQL zawiera wiele wkładek tak:

INSERT INTO `a` (`b`, `c`) VALUES 
    (1, 1), 
    (2, 2), 
    (3, 2); 

INSERT INTO `a` (`b`, `c`) VALUES 
    (1, 1); 

Pole b w tabeli a jest ustawiony jako klucz podstawowy. Kiedy wstawię dokładnie te same dane w dokładnie tej samej strukturze przy użyciu phpMyAdmin, pojawia się następujący błąd: #1062 - Duplicate entry '65533' for key 'PRIMARY'

Dlaczego PDO nie generuje w tym przypadku błędu? Nawet gdy ustawię tryb błędu na wyjątek?

Edit: Jest to struktura tabeli stosowanej do tej konkretnej tabeli

CREATE TABLE IF NOT EXISTS `a` (
    `b` smallint(5) unsigned NOT NULL, 
    `c` smallint(5) unsigned NOT NULL, 
    PRIMARY KEY (`b`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 
+0

http://stackoverflow.com/questions/11102644/pdo-exception-questions-how-to-catch-them –

+0

Mam już go w bloku try/catch, pozwól mi zaktualizować mój kod, aby to wyjaśnić. – Matthijs

+0

Jaki jest dokładny zestaw ograniczeń na stole? – deceze

Odpowiedz

8

to często opisywano jako bug z PDO: https://bugs.php.net/bug.php?id=61613

To rzuci tylko wyjątek, jeśli PIERWSZA Oświadczenie jest nieprawidłowe. Jeśli pierwszy rachunek biegnie gładka, nie dostaniesz żadnego błędu - A twoja pierwsza deklaracja jest ważna:

INSERT INTO `a` (`b`, `c`) VALUES 
    (1, 1), 
    (2, 2), 
    (3, 2); 

jako obejście - lub według zdrowego rozsądku właściwy sposób to zrobić - trzeba przetworzyć zestawów wierszy jeden po drugim (wzięte z raportów o błędach uwagi):

$pdo->beginTransaction(); 
try { 
    $statement = $pdo->prepare($sql); 
    $statement->execute(); 
    while ($statement->nextRowset()) {/* https://bugs.php.net/bug.php?id=61613 */}; 
    $pdo->commit(); 
} catch (\PDOException $e) { 
    $pdo->rollBack(); 
    throw $e; 
} 
+1

Dziękuję bardzo! Nie byłem całkowicie pewien, czy mój kod jest w 100% poprawny, ale nigdy nie znalazłem tego raportu o błędzie (który wyszukuje hasło "Brak błędu PDO, jeśli pierwsza instrukcja SQL grupy jest poprawna", jeśli nie otrzymasz wyjątku w duplikacie wpisu: P) – Matthijs