Hoe kan ik een SELECT query gebruiken in een transactie en de data ophalen van de laatste insert

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Snelle Jaap

Snelle Jaap

04/02/2021 15:54:53
Quote Anchor link
Ik heb de volgende queries die ik in 1 keer uitvoer omdat er gewerkt wordt met het last inserted id en ik zo fouten wil voorkomen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?PHP
$conn
->autocommit(FALSE);
$conn->multi_query('
INSERT INTO orders
(
    producten
)
VALUES
(
    "bla"
)'
);
$conn->multi_query('
UPDATE orders SET order_id = CONCAT(account_id, ".", id)
WHERE id = LAST_INSERT_ID()'
);
$conn->commit();
?>


Nu wil ik in diezelfde transactie de gegevens ophalen uit de orders tabel met het last inserted id.

Met deze query:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?PHP
$conn
->multi_query('
SELECT * FROM orders WHERE id = LAST_INSERT_ID()'
);
?>


Totaal dus op deze manier:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?PHP
$conn
->autocommit(FALSE);
$conn->multi_query('
INSERT INTO orders
(
    producten
)
VALUES
(
    "bla"
)'
);
$conn->multi_query('
UPDATE orders SET order_id = CONCAT(account_id, ".", id)
WHERE id = LAST_INSERT_ID()'
);
$conn->multi_query('
SELECT * FROM orders WHERE id = LAST_INSERT_ID()'
);
$conn->commit();
?>


Ik krijg op deze manier alleen de foutmelding:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
There was an error running the query [Commands out of sync; you can't run this command now]


Hoe komt dit?
Gewijzigd op 04/02/2021 15:57:18 door Snelle Jaap
 
PHP hulp

PHP hulp

03/12/2021 14:39:06
 
Ad Fundum

Ad Fundum

04/02/2021 16:16:10
Quote Anchor link
Waarom doe je
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php $conn->autocommit(FALSE);?>
?
Dan moet je toch eerst het vorige SQL statement handmatig committen voordat je last_insert_id() kunt gebruiken?
Gewijzigd op 04/02/2021 16:17:14 door Ad Fundum
 
Snelle Jaap

Snelle Jaap

04/02/2021 16:19:57
Quote Anchor link
Ad Fundum op 04/02/2021 16:16:10:
Waarom doe je
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php $conn->autocommit(FALSE);?>
?
Dan moet je toch eerst het vorige SQL statement handmatig committen voordat je last_insert_id() kunt gebruiken?


Omdat ik een transactie wil uitvoeren en ik las dat je dat met mysqli op deze manier doet.

"Dan moet je toch eerst het vorige SQL statement handmatig committen voordat je last_insert_id() kunt gebruiken?"

Blijkbaar hoeft dat niet want de update query pakt het juiste id bij LAST_INSERT_ID()
Gewijzigd op 04/02/2021 16:20:19 door Snelle Jaap
 
Ivo P

Ivo P

04/02/2021 17:26:37
Quote Anchor link
je bent je dus nog steeds een hoop ellende op de hals aan het halen, omdat je niet wilt doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT *, CONCAT(account_id, '.', id) FROM orders


danwel in PHP een functie aanroepen om die 2 samen te voegen.

Dat zou al kunnen met

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo $order->geef_ordernummer(); ?>


waarbij jouw object $order dan een functie kent
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
public function geef_ordernummer()
{
   return $this->account_id . '.' . $this->id;
}


ja: het is mogelijk om direct bij de insert je afgeleide data ook in je tabel te krijgen.
maar soms komt dat met een hoop extra werk.

Je bent nu al een dag bezig hiermee, terwijl de recht-toe-recht-aan oplossing heel simpel te maken is.
En daarbij ook flexibel blijft voor het geval je ooit bedenkt dat in het ordernummer dat je toont ook nog het jaartal moet staan of dat je in plaats van de punt een streepje wilt hebben in je weergave.

Toevoeging op 04/02/2021 17:28:16:

en wat betreft je transactie: probeer anders te committen voor je de select query uitvoert (waarbij je eigenlijk vooraf al wist wat daar in kwam te staan, want dat zet je net in de 2 query's ervoor in je database
 
Snelle Jaap

Snelle Jaap

05/02/2021 09:18:24
Quote Anchor link
Klopt, vanwege een check die ik uitvoer wil ik het op deze manier doen, daarnaast heb ik nog nooit met transacties gewerkt dus vind ik het ook wel leuk te leren hoe dat werkt. Kan in de toekomst misschien weer handig zijn.

"en wat betreft je transactie: probeer anders te committen voor je de select query uitvoert (waarbij je eigenlijk vooraf al wist wat daar in kwam te staan, want dat zet je net in de 2 query's ervoor in je database"

Maar wat als twee mensen tegelijkertijd een order erin schieten, en dit script moet het last inserted id ophalen, kan dat dat geen potentiële problemen opleveren wanneer die select query niet ook in de transactie staat?
 
Ivo P

Ivo P

05/02/2021 15:40:35
Quote Anchor link
LAST_INSERT_ID gaat om de laatste insert die jouw verbinding heeft gedaan.

https://dev.mysql.com/doc/c-api/8.0/en/getting-unique-id.html

For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a nonmagic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed.
Gewijzigd op 05/02/2021 15:41:43 door Ivo P
 
Snelle Jaap

Snelle Jaap

05/02/2021 16:17:13
Quote Anchor link
Ivo P op 05/02/2021 15:40:35:
LAST_INSERT_ID gaat om de laatste insert die jouw verbinding heeft gedaan.

https://dev.mysql.com/doc/c-api/8.0/en/getting-unique-id.html

For LAST_INSERT_ID(), the most recently generated ID is maintained in the server on a per-connection basis. It is not changed by another client. It is not even changed if you update another AUTO_INCREMENT column with a nonmagic value (that is, a value that is not NULL and not 0). Using LAST_INSERT_ID() and AUTO_INCREMENT columns simultaneously from multiple clients is perfectly valid. Each client will receive the last inserted ID for the last statement that client executed.


Ah oke dat wist ik niet. Ik dacht dat hij het last inserted id van de hele tabel pakte. Dan kan ik de SELECT query inderdaad buiten de commit zetten.
Gewijzigd op 05/02/2021 16:21:40 door Snelle Jaap
 
Ad Fundum

Ad Fundum

05/02/2021 17:03:22
Quote Anchor link
Achja, dat is ook zo met last_insert_id(). Ik had alleen gemist dat het met multi_query() ging om een functie van mysqli. (de code $conn = new mysqli; had geholpen)

Als ik in de handleiding kijk zie ik dat multi_query() uit zichzelf geen transacties uitvoert. De functie multi_query() voert alleen meerdere queries achter elkaar uit, waarbij je ongebruikte resultaten moet flushen voordat je query() weer kunt gebruiken. Je maak het iets gecompliceerder dan nodig.

Je kunt losse queries uitvoeren met mysqli::query(), zelfs een transactie starten met 'START TRANSACTION'. De AUTO_INCREMENT waarde kan je ook weer inlezen met mysqli::$insert_id, en hergebruiken in een volgende mysqli::query(). Dat lijkt mij overzichtelijker.
Gewijzigd op 05/02/2021 17:04:39 door Ad Fundum
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.