PHP MySQL PDO: получить последнюю вставленную строку, а не ID
В настоящее время у меня есть скрипт для автоматической вставки новых данных при использовании формы для добавления нового элемента.
я использую
public string PDO::lastInsertId ([ string $name = NULL ] )
Логика конечно. Теперь мне только интересно, может ли это вызвать какие-либо проблемы в случае, если в таблице нет поля идентификатора и поля автоинкремента.
Помимо того, что это означает, что используется плохая структура базы данных. Я хочу убедиться, что эта рутина работает в любой ситуации. Хорошая база данных или плохая структура базы данных. Это не должно иметь значения.
Я имею в виду, что я хотел бы вернуть строку с данными, чтобы я мог их искать.
НАПРИМЕР
1
Вставьте новые данные в базу данных
$query = $pdo->prepare("INSERT INTO `tablename` SET `data_name`='John', `data_familyname`='Doe', 'data_age`=45, `data_wife`='Sarah Doe'");
$query->execute();
2
Получить последний вставленный ряд полностью
///$LastID = $pdo->lastInsertId();
$query = $pdo->prepare("SELECT `data_name`,`data_familyname`,`data_age`,`data_wife` FROM `tablename` WHERE LAST IDFIELD = ".$pdo->lastInsertId());
$query->execute();
$row = $query->fetch();
Ряд содержит
array(
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
3
Затем обновите последнюю вставленную строку точно такими же данными, как только что вставленные
$query = $pdo->prepare("UPDATE `tablename` SET `data_name`='Chris' WHERE `data_name`=? AND `data_familyname`=? AND 'data_age`=? AND `data_wife`=?");
$query->execute(array_values($row));
Последний запрос в основном:
UPDATE `tablename` SET `data_name`='Chris'
WHERE `data_name`='John' AND `data_familyname`='Doe' AND 'data_age`='45' AND `data_wife`='Sarah Doe'
Конечно, существует вероятность того, что дубликаты данных существуют. И вы хотите изменить только последний ряд. Вот где я имел в виду, помимо того, что база данных имеет хорошую структуру.
Но для предотвращения дублирования данных можно добавить:
Ряд содержит
array(
'data_id' => 20,
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
Дело в том
Шаг 2
Не работает, так как я только сделал это за пару минут. Однако я хотел бы знать, существуют ли какие-либо подобные функции или процедуры, которые делают то же самое, что я только что упомянул.
Надеюсь, что понятно, чего я хочу.
Мое решение в конечном итоге:
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->query("SELECT LAST_INSERT_ID()");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$lastID = $result['LAST_INSERT_ID()'];
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` WHERE `'.$AutoIncrementField.'` = ?');
$stmt->execute(array($lastID));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo print_r($result);
Результат:
Array
(
[pdo_id] => 64
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
Но поле AutoIncrement кажется существенным.
Второе решение, но все еще с полем AutoIncrement.
(по предложению Эдвина Ламбрегта)
Обратите внимание, что это решение не является отказоустойчивым!!! Потому что запрос выбирает последнюю вставленную строку... Но ВСЕМИ экземплярами! Следовательно, если другой пользователь только что вставил новую строку... Вы увидите его ввод, а не ваш. Это может произойти, если обновление происходит между ними.
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` ORDER BY `'.$AutoIncrementField.'` DESC LIMIT 0,1');
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
Результат:
Array
(
[pdo_id] => 67
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
2 ответа
Я не уверен, что ваш вопрос, но, чтобы не испортить вещи в вашей таблице, вы должны реализовать это:
Есть
PK
(первичный ключ) на столе. Он предоставляет вам способ уникальной идентификации каждой строки. Это должно быть поле или комбинация полей, которые однозначно идентифицируют каждую строку. Теоретически он лучший кандидат наPK
является внутренним свойством объекта, хранящимся в таблице, которое идентифицирует объект. Например, дляCountry
стол хороший кандидат наPK
это полное название страны. В реальном миреAUTO_INCREMENT
поля были изобретены потому что:- в некоторых таблицах просто нет столбца или набора столбцов, которые можно использовать как
PK
; например, таблица, используемая для хранения записей журнала, сгенерированных программой - все записи должны быть сохранены, даже если некоторые из них идентичны; искусственныйPK
создан для них с помощьюAUTO_INCREMENT
поле; - когда тип столбца наилучшего кандидата для
PK
являетсяstring
(название страны в примере выше) или когда кандидат наPK
представляет собой набор из двух или более столбцов, используя его какPK
окажет негативное влияние на производительность на столе; искусственныйPK
(создан какAUTO_INCREMENT
поле integer) создает меньший индекс, который повышает скорость запросов, которые его используют.
- в некоторых таблицах просто нет столбца или набора столбцов, которые можно использовать как
На
INSERT
Вы можете сгенерировать значение дляPK
и поместите его в запрос или положитесь на базу данных, чтобы сгенерировать ее для вас (еслиPK
являетсяAUTO_INCREMENT
поле).- Если вы генерируете значение для
PK
Вы должны быть уверены, что он еще не существует в таблице. Вы можете либо проверить, не существует ли он раньшеINSERT
или вы можете попытатьсяINSERT
и проверьте, удалось ли это. Даже если вы проверите раньше,INSERT
все еще может потерпеть неудачу, потому что другой экземпляр скрипта может работать одновременно, генерировать иINSERT
то же значение дляPK
, В этой ситуации вам нужно сгенерировать другое значение и попытатьсяINSERT
снова, и этот рабочий процесс повторяется, пока он не будет успешным. Это не похоже на хорошую стратегию для меня. Вы можете позволить базе данных генерировать уникальное значение для вашего
PK
(предоставляяNULL
дляPK
вINSERT
запрос или не предоставляя его вообще) затем спросите его о значении, которое он сгенерировал.MySQL
обеспечиваетLAST_INSERT_ID()
функция для этой цели. Выдержка из документации:Сгенерированный идентификатор сохраняется на сервере для каждого соединения. Это означает, что значение, возвращаемое функцией данному клиенту, является первым
AUTO_INCREMENT
значение, сгенерированное для самого последнего утверждения, влияющего наAUTO_INCREMENT
колонка этого клиента. На это значение не могут повлиять другие клиенты, даже если они генерируютAUTO_INCREMENT
ценности свои. Такое поведение гарантирует, что каждый клиент может получить свой собственный идентификатор, не заботясь об активности других клиентов и не нуждаясь в блокировках или транзакциях.База данных заботится обо всем: значение уникально, оно не мешает другим экземплярам скрипта (или даже другому коду), который пытается вставить в ту же таблицу в одно и то же время;
INSERT
успешно,PK
является уникальным, я получаю обратно значение, которое идентифицирует мою строку, а не чью-либо строку.
- Если вы генерируете значение для
Наличие дополнительного столбца, который не является внутренним свойством сущностей, хранящихся в таблице, является небольшой ценой, чтобы заплатить за выгоды, которые она производит.
Это всего лишь ориентир и искусственный AUTO_INCREMENT
столбец следует добавлять только тогда, когда это помогает. В приведенном выше примере с таблицей стран AUTO_INCREMENTED
колонка для PK
не нужно:
- таблица содержит всего несколько сотен строк; в нем нет вставок или удалений (на самом деле они есть, но только время от времени; возможно, ваше приложение будет удалено до изменения в
Country
стол нужен); - есть хороший кандидат на
PK
: этоISO-3166
код страны; есть даже два вида этого: 2-буквенный и 3-буквенный - выберите свой любимый; этоCHAR[2]
(или жеCHAR[3]
) и потому что стол такой маленькийPK
никак не влияет на производительность.
Получение последней вставленной записи / строки, безусловно, возможно без использования идентификаторов.
Синтаксис MySQL:
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1
Он просто покажет последнюю вставленную запись.