У меня странная проблема с тем, что PDO не бросает исключение, когда вставлено дублирующее значение. В этом случае я ожидал ошибки.
Соответствующий код:
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 }
Файл с данными SQL содержит несколько вложений, например:
INSERT INTO `a` (`b`, `c`) VALUES (1, 1), (2, 2), (3, 2); INSERT INTO `a` (`b`, `c`) VALUES (1, 1);
Поле b
в таблице a
устанавливается как первичный ключ. Когда я вставляю точные данные в той же самой структуре, используя phpMyAdmin, я получаю эту ошибку: #1062 - Duplicate entry '65533' for key 'PRIMARY'
Почему PDO не вызывает ошибку в этом случае? Даже когда я установил режим ошибки в исключение?
Изменить: это структура таблицы, используемая для этой конкретной таблицы.
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;
Об этом часто сообщалось как ошибка с PDO
: https://bugs.php.net/bug.php?id=61613
Он выдает исключение только в том случае, если FIRST Statement недействителен. Если первый оператор работает плавно, вы не получите никакой ошибки. И ваш первый оператор действителен:
INSERT INTO `a` (`b`, `c`) VALUES (1, 1), (2, 2), (3, 2);
как обходной путь – или, согласно вашему здравому смыслу, правильный способ сделать это – вам нужно обрабатывать ряды по одному (взятые из комментариев к сообщениям об ошибках):
$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; }