2015-09-16 7 views
9

Ho uno strano problema con PDO che non genera un'eccezione quando viene inserito un valore duplicato. In questo caso mi aspettavo un errore.PHP PDO non genera eccezioni sull'inserto della chiave duplicata

Il codice rilevante:

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 
} 

Il file con i dati di SQL contiene più inserti in questo modo:

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

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

Il campo b nella tabella a è impostato per essere la chiave primaria. Quando inserisco esattamente gli stessi dati nella stessa identica struttura usando phpMyAdmin ottengo questo errore: #1062 - Duplicate entry '65533' for key 'PRIMARY'

Perché PDO non genera un errore in questo caso? Anche quando imposto la modalità di errore in eccezione?

Edit: Questa è la struttura della tabella utilizzata per questa tabella specifica

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

Ce l'ho già in un blocco try/catch, permettimi di aggiornare il mio codice per chiarirlo. – Matthijs

+0

Qual è il limite esatto impostato sul tavolo? – deceze

risposta

8

Questo è stato spesso segnalato come bug con PDO: https://bugs.php.net/bug.php?id=61613

si getterà solo un'eccezione se l'PRIMO La dichiarazione non è valida Se la prima istruzione scorre liscio, non sarà possibile ottenere alcun errore - E la tua prima affermazione è valida:

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

come una soluzione - o secondo il buon senso il modo giusto di farlo - è necessario per elaborare i set di righe one-by-one (preso dai commenti segnalazioni di bug):

$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

Grazie mille! Non ero completamente sicuro che il mio codice fosse corretto al 100% ma non ho mai trovato questa segnalazione di bug (chi cerca "Nessun errore PDO se la prima istruzione SQL di un gruppo è valida" quando non si ottiene un'eccezione su una voce duplicata: P) – Matthijs