Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > LAST_INSERT_ID() возвращает ноль.


Автор: malor 4.7.2013, 02:07
Создается запись в БД.
Сразу после этого пытаемся получить её ID:

Код
  $SQL = ' SELECT LAST_INSERT_ID() AS last_id ';
  $st = $db->query($SQL);

  $rowcount = $st->rowCount();
  if ($rowcount == 0)
  {
    echo 'Не получили ID последней вставленной записи.';
    exit;
  }

  $st->setFetchMode(PDO::FETCH_ASSOC);
  $row = $st->fetch();
  if ($row)
  {
    $inserted_id = $row['last_id'];  
  }      

  $newconsultation = 'Location: add_cons.php?id_man='.$inserted_id;
  header($newconsultation); 


Так вот почему-то  $inserted_id  равна нулю.
Инет усеян вопросами про то, отчего "LAST_INSERT_ID()" возвращает 0. Причем автоинкрементный столбец есть в таблице. 
Пишут, что MySQL успевает разорвать одно соединение, и создать новое, а в этом новом нет памяти о прошлом, поэтому и ноль.
 smile 
Где-то советуют сразу объединить текст INSERT-запроса и запроса про "LAST_INSERT_ID()", разделив их точкой с запятой.

Но четкого ответа нет. Это ж ключевой вопрос использования связки MySQL+PHP.
Не может не быть решения.
 smile 
MySQL 5.5.29

Автор: Arantir 4.7.2013, 03:04
Вы, случайно, после добавления записи соединение не закрываете?
Добавление новой строки и получение LAST_INSERT_ID выполняются в одном и том же запросе?

Если запись добавлялась давно (как минимум не в текущем запросе, а в прошлых), то текущую позиций автоинкремента можно получить из инфы о таблице из поля Auto_increment:
Код

SHOW TABLE STATUS LIKE 'table_name';

Код

~----------+-----------+----------------+---------------------+--------~
 ex_length | Data_free | Auto_increment | Create_time         | Update_
~----------+-----------+----------------+---------------------+--------~
         0 |   9437184 |            222 | 2013-06-29 02:00:06 | NULL   
~----------+-----------+----------------+---------------------+--------~

Автор: krundetz 4.7.2013, 09:44
malor, а почему не используете встроенные средства PDO, раз запросы посылаете через него?
http://php.net/manual/en/pdo.lastinsertid.php

Автор: malor 4.7.2013, 11:40
Цитата(krundetz @  4.7.2013,  09:44 Найти цитируемый пост)
почему не используете встроенные средства PDO, раз запросы посылаете через него?

Именно его и и спользовал сначала. Аналогичное поведение было. Поэтому перешел на "LAST_INSERT_ID()".

Цитата(Arantir @  4.7.2013,  03:04 Найти цитируемый пост)
после добавления записи соединение не закрываете?

Нет.

Цитата(Arantir @  4.7.2013,  03:04 Найти цитируемый пост)
Добавление новой строки и получение LAST_INSERT_ID выполняются в одном и том же запросе?
Нет. Стоит попробовать?
Вставка записи выполнялась строкой:
$rows = $db->exec($SQL);

Поучение ID последней записи:
$st = $db->query($SQL);

А если SQL-запросы слепить в одно, то что использовать ? Вариант "query" ?


Цитата(Arantir @  4.7.2013,  03:04 Найти цитируемый пост)
текущую позиций автоинкремента можно получить из инфы о таблице из поля Auto_increment
Но её могут уже изменить другие пользователи, работающие с базой! Если б такой способ был уместен, 
то и незачем бы было придумывать создателям функцию "LAST_INSERT_ID()".

Автор: AVA12 4.7.2013, 13:00
Смутно подозреваю, что ошибка в минус семнадцатой строке.

Ноль может вернуться, если ни одной записи не вставлено или если предыдущий запрос выдал ошибку.

Возможно, объект PDO настроен так, что в случае ошибки молча сохраняет ее код (так и есть по умолчанию), который нужно проверять.

Автор: Arantir 4.7.2013, 16:49
Цитата(malor @  4.7.2013,  10:40 Найти цитируемый пост)
Нет. Стоит попробовать?

Я имел ввиду http-запрос. Не очень четко выразился. Проще говоря - открытие страницы в браузере, то есть выполнение php-скрипта. Ведь по окончании скрипта соединение с БД закроется и сессия пропадет вместе с LAST_INSERT_ID.
Цитата(malor @  4.7.2013,  01:07 Найти цитируемый пост)
Пишут, что MySQL успевает разорвать одно соединение, и создать новое, а в этом новом нет памяти о прошлом, поэтому и ноль.

Не думаю, что это возможно. Страничка сервером генерируется доли секунды. Вы получаете LAST_INSERT_ID через какие-то миллисекунды после добавления строки. Если бы БД так быстро закрывала и открывала соединения, то сервер БД бы просто упал =)


А запрос точно успешен? Попробуйте проделать ту же последовательность запросов вручную через консоль mysql.

Автор: Fortop 4.7.2013, 18:16
Цитата(malor @  4.7.2013,  02:07 Найти цитируемый пост)
Создается запись в БД.
Сразу после этого пытаемся получить её ID:

где в приведенном коде это видно?

Автор: krypt3r 5.7.2013, 06:21
Ни DDL таблицы, ни самого запроса вставки, ни перехвата исключений, не видно, используются ли транзакции...

Автор: krundetz 5.7.2013, 11:44
А формат таблиц не innoDB случаем?

Автор: Fortop 5.7.2013, 15:27
Цитата(krundetz @  5.7.2013,  11:44 Найти цитируемый пост)
А формат таблиц не innoDB случаем? 

Что это меняет?

Автор: krundetz 8.7.2013, 08:52
А INSERT IGNORE случаем не используете, тогда LAST_INSERT_ID() совершенно верно возвращает 0, если не было ни одной вставки.

Цитата

Что это меняет?

понимание ситуации более четкое.

ТС выложите пожалуйста реальный пример воспроизводящий ваш случай, а не этот обрывок.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)