1 Востаннє редагувалося Betterthanyou (02.02.2018 11:35:02)

Тема: [ВИРІШЕНО][PDO] як отримати останнє id в середині транзакції

ВИРІШЕНО!
Є 4 таблиці
3 містять інформацію, 4 служить для об'єднання тих трьох в одну, зв'язок таблиць 1 до 1
http://replace.org.ua/misc.php?action=pun_attachment&item=1726&download=0
(я знаю що з цих таблиць можна зробити одну, але в моєму випадку так не потрібно робити...)

Мені потрібно вставляти дані так, щоб коли трапиться будь який збій (помилка, пропало з'єднання т.д.), то запит на вставлення був відхилений. Нехай вставляється все що потрібно, або нічого. Для вирішення цієї задачі я вибрав транзакцію

Після вставлення запису (в будь яку із трьох таблиць) мені потрібно взяти останнє id та вставити його у четверту таблицю ("bbcode"), для того щоб утворити відношення 1 до 1

Проблема в тому що останнє id вставляється тільки один раз
http://replace.org.ua/extensions/om_images/img/5a712f99731b4/Untitghled.png

Два варіанти що я пробував

1
Використав функцію lastInsertId з PDO

/*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)"
        );
}

2
Використав функцію LAST_INSERT_ID() з mysql

/*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())"
        );
}

...

Прихований текст
тут спрацювала магія форуму і я здогадався що не так

...

Вирішення
Проблема була в іншому, кожний раз я робив нову вставку...
Виправити це можна так, спочатку зібрати текстовий запит

/*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);

Потім вже в циклі зв'язати(bind) значення. Рядок 18-19

/*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);
}

Після циклу виконати запит

/*insert 'last insert id' to the bbcode table*/
$sqlQuery2->execute();

і завершити транзакцію

/*check if the transaction is completed*/
if($this->conn->commit())
    $this->currentState = 'Inserting was successfully done';
else
    throw new Exception('Insert failed');

Якщо потрібно заборонити пусті поля достатньо забрати

if($value == '')
    continue;

з рядків 8-9 у збирані запиту та рядків 5-6 у збирані іншого запиту (sqlQuery1)

Post's attachments

Untidfgtled.png 25.03 kb, 71 downloads since 2018-01-31 

Подякували: 0xDADA11C7, /KIT\, 221VOLT4

2

Re: [ВИРІШЕНО][PDO] як отримати останнє id в середині транзакції

еее, так це у вас не просто пдо, це ж мускуль

в посгресі не LAST_INSERT_ID() а returning id при вставці, для прикладу

це так, ліричне доповнення))

https://blog.clever-games.win/
Це ще не кінець. Це навіть не початок кінця. Але, можливо, це кінець початку.
Зростання мудрості можна точно вимірювати ступенем зменшення злоби.
///// у творчій відпустці. не турбувати /////
Подякували: Betterthanyou1