Вставьте строки для отношения m: m (pupil-вечером_activity) последовательно

У меня есть три таблицы в моей базе данных (MySQL / InnoDB): pupil, evening_activity а также pupil_evening_activity, Как вы можете догадаться, есть m:m отношения между pupil а также evening_activity,

У меня есть HTML-форма для вставки новых учеников и ассоциирования с ними вечерних мероприятий. После отправки формы я хотел бы добавить учеников и связанные с ними виды деятельности в базу данных. Итак, я написал этот код:

$db = new PDO('mysql:host=localhost;dbname=school;charset=utf8','root', '****');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";
$st = $db->prepare($sql);
$st->execute();

foreach ($eveningActivityIds as $eveningActivityId) {
$sql = "INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES
(?, ?)
";
$st = $db->prepare($sql);
$st->execute(array($db->lastInsertId(), $eveningActivityId));
}

} catch (PDOException $e) {

echo $e->getMessage();
return false;

}

Я написал этот код ожидая PDO::lastInsertId() всегда возвращает последний вставленный идентификатор ученика, но я обнаружил, что это действительно возвращает последний вставленный id на всю базу данных. Так что, если в гипотетический вставлен другой ряд teacher Таблица как раз перед призывая к $db->lastInsertId() в коде выше, $db->lastInsertId() вернет id вставленного учителя вместо id последнего ученика.

Итак, как я могу получить 100% безопасность последней вставленной id из pupil стол после отправки формы?

Я думал об использовании транзакции и MAX() функция, чтобы получить последний id вставлен в pupil стол, но я не уверен в этом.

1

Решение

Ошибочно иметь $ db-> lastInsertId () в цикле foreach, так как он может возвращать непредсказуемые значения. Пожалуйста, рассмотрите код ниже:

try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";

$st = $db->prepare($sql);
$st->execute();

// save pupil id into variable here:
$pupil_id = $db->lastInsertId();

// also there's no need to prepare the statement on each iteration:
$sql = "INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES
(?, ?)";
$st = $db->prepare($sql);

foreach ($eveningActivityIds as $eveningActivityId) {
$st->execute(array($pupil_id, $eveningActivityId));
}
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}

Оптимизация: вы можете вставить все действия в одном утверждении. Это экономит несколько запросов

try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";

$st = $db->prepare($sql);
$st->execute();

// save pupil id into variable here:
$pupil_id = $db->lastInsertId();

$sql = 'INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES ';

$values = array();

foreach ($eveningActivityIds as $eveningActivityId) {
$sql .= '(?, ?),';
array_push($values, $pupil_id, $eveningActivityId);
}

$st = $db->prepare(chop($sql, ','));
$st->execute($values);
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]