Тема: [ВИРІШЕНО][PDO] як отримати останнє id в середині транзакції
Є 4 таблиці
3 містять інформацію, 4 служить для об'єднання тих трьох в одну, зв'язок таблиць 1 до 1
(я знаю що з цих таблиць можна зробити одну, але в моєму випадку так не потрібно робити...)
Мені потрібно вставляти дані так, щоб коли трапиться будь який збій (помилка, пропало з'єднання т.д.), то запит на вставлення був відхилений. Нехай вставляється все що потрібно, або нічого. Для вирішення цієї задачі я вибрав транзакцію
Після вставлення запису (в будь яку із трьох таблиць) мені потрібно взяти останнє id та вставити його у четверту таблицю ("bbcode"), для того щоб утворити відношення 1 до 1
Проблема в тому що останнє id вставляється тільки один раз
Два варіанти що я пробував
1
Використав функцію lastInsertId з PDO
[code=PHP]
/*insert all fields to the database*/
foreach($this->code as $key => $value)
{
////////////////////////////////////////////////////////////////
/*prepare to insert*/
$sqlQuery = $this->conn->prepare(
"INSERT INTO $key (code) VALUES (:code)"
);
/*bind parameters*/
$sqlQuery->bindParam(':code', $value);
/*execute Sql query to insert*/
$sqlQuery->execute();
////////////////////////////////////////////////////////////////
/*insert 'last insert id' to the bbcode table*/
$lastInsertId = $this->conn->lastInsertId($key);
$this->conn->exec(
"INSERT INTO doc_maker.bbcode (id$key)
VALUES ($lastInsertId)"
);
}
[/code]
2
Використав функцію LAST_INSERT_ID() з mysql
[code=PHP]
/*insert all fields to the database*/
foreach($this->code as $key => $value)
{
////////////////////////////////////////////////////////////////
/*prepare to insert*/
$sqlQuery = $this->conn->prepare(
"INSERT INTO $key (code) VALUES (:code)"
);
/*bind parameters*/
$sqlQuery->bindParam(':code', $value);
/*execute Sql query to insert*/
$sqlQuery->execute();
////////////////////////////////////////////////////////////////
/*insert 'last insert id' to the bbcode table*/
$this->conn->exec(
"INSERT INTO doc_maker.bbcode (id$key)
VALUES (LAST_INSERT_ID())"
);
}
[/code]
...
тут спрацювала магія форуму і я здогадався що не так
...
Вирішення
Проблема була в іншому, кожний раз я робив нову вставку...
Виправити це можна так, спочатку зібрати текстовий запит
[code=PHP]
/*set the initial values*/
$strQuery2 = 'INSERT INTO doc_maker.bbcode (';
$strQuery2tables=array();
$strQuery2values=array();
/*filling*/
foreach($this->code as $key => $value)
{
if($value=='')
continue;
array_push($strQuery2tables, "id$key");
array_push($strQuery2values, ":$key");
}
/*build the query*/
$strQuery2 .= implode(', ', $strQuery2tables);
$strQuery2 .= ') VALUES(';
$strQuery2 .= implode(', ', $strQuery2values);
$strQuery2 .= ')';
$sqlQuery2 = $this->conn->prepare($strQuery2);
[/code]
Потім вже в циклі зв'язати(bind) значення. Рядок 18-19
[code=PHP]
/*insert all fields to the database*/
foreach($this->code as $key => $value)
{
/*if one of fields is empty then 'continue'*/
if($value=='')
continue;
////////////////////////////////////////////////////////////////
/*prepare to insert*/
$sqlQuery1 = $this->conn->prepare(
"INSERT INTO $key (code) VALUES (:code)"
);
/*bind parameters*/
$sqlQuery1->bindValue(':code', $value, PDO::PARAM_STR);
/*execute Sql query to insert*/
$sqlQuery1->execute();
////////////////////////////////////////////////////////////////
/*bind bbcode parameters*/
$lastInsertId = $this->conn->lastInsertId($key);
$sqlQuery2->bindValue(":$key", $lastInsertId, PDO::PARAM_INT);
}
[/code]
Після циклу виконати запит
[code=PHP]
/*insert 'last insert id' to the bbcode table*/
$sqlQuery2->execute();
[/code]
і завершити транзакцію
[code=PHP]
/*check if the transaction is completed*/
if($this->conn->commit())
$this->currentState = 'Inserting was successfully done';
else
throw new Exception('Insert failed');
[/code]
Якщо потрібно заборонити пусті поля достатньо забрати
if($value == '')
continue;
з рядків 8-9 у збирані запиту та рядків 5-6 у збирані іншого запиту (sqlQuery1)
Untidfgtled.png 25.03 kb, 171 downloads since 2018-01-30