В настоящее время у меня есть скрипт для автоматической вставки новых данных при использовании формы для добавления нового элемента.
я использую
public string PDO::lastInsertId ([ string $name = NULL ] )
Логика конечно. Теперь мне только интересно, может ли это вызвать какие-либо проблемы в случае, если в таблице нет поля идентификатора и поля автоинкремента.
Помимо того, что это означает, что используется плохая структура базы данных.
Я хочу убедиться, что эта рутина работает в любой ситуации. Хорошая база данных или плохая структура базы данных. Это не должно иметь значения.
Я имею в виду, что я хотел бы вернуть строку с данными, чтобы я мог их найти.
НАПРИМЕР.
Вставить новые данные в базу данных
$query = $pdo->prepare("INSERT INTO `tablename` SET `data_name`='John', `data_familyname`='Doe', 'data_age`=45, `data_wife`='Sarah Doe'");
$query->execute();
Получить последний вставленный ряд полностью
///$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'
);
Затем обновите последнюю вставленную строку точно такими же данными, как только что вставленные
$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'
);
Дело в том
Не работает, так как я только сделал это пару минут на ходу. Однако я хотел бы знать, есть ли какие-либо подобные функции или процедуры, которые делают то же самое, что я только что упомянул.
Надеюсь, что понятно, чего я хочу.
$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 кажется существенным.
(по предложению Эдвина Ламбрегта)
Обратите внимание, что это решение не является отказоустойчивым !!! Потому что запрос выбирает последнюю вставленную строку … Но ВСЕМИ экземплярами! Следовательно, если другой пользователь просто вставил новую строку … Вы увидите его ввод, а не ваш. Это может произойти, если обновление происходит между ними.
$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
)
Я не уверен, что ваш вопрос, но, чтобы не испортить вещи в вашей таблице, вы должны реализовать это:
Есть PK
(первичный ключ) на столе. Он предоставляет вам способ уникальной идентификации каждой строки. Это должно быть поле или комбинация полей, которые однозначно идентифицируют каждую строку. Теоретически он лучший кандидат на PK
является внутренним свойством объекта, хранящимся в таблице, которое идентифицирует объект. Например, для Country
стол хороший кандидат на PK
это полное название страны. В реальном мире AUTO_INCREMENT
поля были изобретены потому что:
PK
; например, таблица, используемая для хранения записей журнала, сгенерированных программой — все записи должны быть сохранены, даже если некоторые из них идентичны; искусственный PK
создан для них с помощью AUTO_INCREMENT
поле;PK
является string
(название страны в примере выше) или когда кандидат на PK
представляет собой набор из двух или более столбцов, используя его как PK
окажет негативное влияние на производительность на столе; искусственный PK
(создан как AUTO_INCREMENT
целое поле) создает меньший индекс, который повышает скорость запросов, которые его используют.На 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
код страны; есть даже две разновидности: двухбуквенная и трехбуквенная — выберите свою любимую; это CHAR[2]
(или же CHAR[3]
) и потому что стол такой маленький PK
никак не влияет на производительность.Получение последней вставленной записи / строки, безусловно, возможно без использования идентификаторов.
Синтаксис MySQL:
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1
Он просто покажет последнюю вставленную запись.