PDO mysql: как узнать, прошла ли вставка успешно


96

Я использую PDO для вставки записи (mysql и php)

$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();

Есть ли способ узнать, успешно ли он вставлен, например, если запись не была вставлена, потому что это была дубликат?

Изменить: конечно, я могу посмотреть базу данных, но я имею в виду программную обратную связь.

Ответы:


141

PDOStatement->execute()возвращает true в случае успеха. Там также PDOStatement->errorCode()вы можете проверить наличие ошибок.


1
Как вы смотрите на значение execute ()?
Mallow

29
Больше ничего подобного, $ value = $ stmt-> execute (); if ($ value) {// true} else {// false}
Ólafur Waage

23
Или вы можете просто сделатьif ($stmt->execute()) { //true }
Гэвин

2
Согласуются ли PDOStatement->execute()и PDOStatement->errorCode()полностью друг с другом? Есть ли обстоятельства, при PDOStatement->errorCode()которых что-то есть, но PDOStatement->execute()возвращает true? Или когда PDOStatement->execute()возвращается false, но PDOStatement->errorCode()ничего не имеет?
datasn.io

2
Но INSERT IGNORE также вернет истину, даже если новая запись не будет вставлена
Koffeehaus

26

Учитывая, что наиболее рекомендуемый режим ошибок для PDO - это ERRMODE_EXCEPTION, никакая прямая execute()проверка результатов никогда не будет работать . Поскольку выполнение кода даже не достигнет условия, предложенного в других ответах.

Итак, есть три возможных сценария обработки результата выполнения запроса в PDO:

  1. Чтобы сказать об успехе, проверка не требуется. Просто следите за ходом своей программы.
  2. Чтобы справиться с неожиданной ошибкой, придерживайтесь того же принципа - код немедленной обработки не требуется. В случае ошибки базы данных будет сгенерировано исключение, и оно будет передано обработчику ошибок всего сайта, что в конечном итоге приведет к появлению стандартной страницы с ошибкой 500.
  3. Чтобы обработать ожидаемую ошибку, например дублированный первичный ключ, и если у вас есть определенный сценарий для обработки этой конкретной ошибки, используйте try..catchоператор.

Для обычного пользователя PHP это звучит немного чуждо - как же, чтобы не проверить прямой результат операции? - но именно так работают исключения - вы проверяете ошибку в другом месте. Раз и навсегда. Чрезвычайно удобно.

Итак, в двух словах: в обычном коде обработка ошибок не требуется. Просто сохраните свой код как есть:

$stmt->bindParam(':field1', $field1, PDO::PARAM_STR);
$stmt->bindParam(':field2', $field2, PDO::PARAM_STR);
$stmt->execute();
echo "Success!"; // whatever

В случае успеха он сообщит вам об этом, в случае ошибки он покажет вам обычную страницу с ошибкой, которую ваше приложение показывает для такого случая.

Только в случае, если у вас есть сценарий обработки, отличный от простого сообщения об ошибке, поместите оператор вставки в try..catchоператор, проверьте, была ли это ожидаемая вами ошибка, и обработайте ее; или - если ошибка была другой - повторно вызовите исключение, чтобы обработчик ошибок всего сайта мог обработать его обычным способом. Ниже приведен пример кода из моей статьи об обработке ошибок с помощью PDO :

try {
     $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data);
} catch (PDOException $e) {
    if ($e->getCode() == 1062) {
        // Take some action if there is a key constraint violation, i.e. duplicate name
    } else {
        throw $e;
    }
}
echo "Success!";

В приведенном выше коде мы проверяем конкретную ошибку, чтобы предпринять какие-либо действия, и повторно генерируем исключение для любой другой ошибки (например, такой таблицы нет), о которой будет сообщено программисту.

И опять же - просто сказать пользователю что-то вроде «Ваша вставка прошла успешно» никаких условий не требуется.


Что означает «успех»? Означает ли это, что вставлена ​​новая строка, или это означает, что ошибки нет?
Martin AJ

Для запроса INSERT это почти то же самое.
Your Common Sense

Вы правы .. Подскажите, пожалуйста, как насчет query()функции? Могу ли я использовать try-catch query()вместо prepared()->execute()?
Martin AJ

3
Вы никогда не должны использовать query () для вставки в первую очередь. Вставка означает, что ввод есть, а ввод означает, что он должен быть подготовлен.
Your Common Sense

1
Используя MySQL, мне пришлось проверить, есть ли $ e-> errorInfo [1] == 1062, чтобы убедиться, что вставка не удалась, потому что $ e-> getCode () всегда
равно 23000.


9

Если запрос на обновление выполняется со значениями, соответствующими текущей записи базы данных, он $stmt->rowCount()вернется, так 0как никакие строки не были затронуты. Если у вас есть if( rowCount() == 1 )проверка на успех, вы подумаете, что обновление завершилось неудачно, если оно не прошло, но значения уже были в базе данных, поэтому ничего не изменится.

$stmt->execute();
if( $stmt ) return "success";

Это не сработало для меня, когда я попытался обновить запись с уникальным ключевым полем, которое было нарушено. Запрос вернул успех, но другой запрос вернул старое значение поля.


3
Если вам НУЖНО вставить запись, лучше всего проверить это так ............................. ..... .................. if($stmt->execute() && ($stmt->rowCount()>0))
jave.web

4

Вы можете проверить количество строк

    $sqlStatement->execute( ...);
    if ($sqlStatement->rowCount() > 0)
    {
        return true;
    }

Ссылка на документы всегда полезна @YourCommonSense. В нем говорится, что «такое поведение не гарантируется для всех баз данных и на него не следует полагаться для переносимых приложений», но ограничено, во-первых, выбором, а во-вторых, поддерживается для mysql, который является предметом этого сообщения.
Crafter

просто введите «pdo rowcount» в адресной строке браузера и щелкните первую ссылку. печатать нужно меньше, чем комментарий
Ваш здравый смысл

1
@crafter Правильно. Он говорит, что rowCount () может быть ненадежным для SELECTзапросов (и даже там в документации говорится о нескольких запросах). Он ничего не говорит о том DELETE, INSERTили UPDATE, которые , кажется , будет хорошо работать (речь шла о INSERTзапросе). Однако я новичок в PDO, и если я ошибаюсь и у кого-то есть другие ссылки, напишите их здесь. Мне интересно узнать, есть ли реальные недостатки у трех приведенных выше команд.
StanE

1

Использовать идентификатор как первичный ключ с автоматическим приращением

$stmt->execute();
$insertid = $conn->lastInsertId();

инкрементный идентификатор всегда больше нуля даже в первой записи, это означает, что он всегда будет возвращать истинное значение для id coz больше нуля означает истину в PHP

if ($insertid)
   echo "record inserted successfully";
else
   echo "record insertion failed";

Что делать, если мне не нужно автоматически увеличивать поле в моей таблице?
Your Common Sense

Кто дан? ты? с помощью RESTFul API, который так широко используется, автоматическое увеличение идентификатора похоже на обязательное.
джемпер rbk

Почему у кого-то нет основного столбца и столбца с автоматическим приращением или любого другого столбца последовательности? Если нужен метод проверки, добавьте любой последовательный столбец. Если это решение не для Вас, не добавляйте его. Для меня это хорошо, я всегда использую столбец с последовательным и автоматическим приращением, поэтому у меня всегда есть способ проверить, был ли мой запрос успешным.
Самуэль Рамзан

0

PDOStatement-> execute () может вызвать исключение

так что ты можешь сделать это

try
{
PDOStatement->execute();
//record inserted
}
catch(Exception $e)
{
//Some error occured. (i.e. violation of constraints)
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.