W3Schools zegt:
If we perform an INSERT or UPDATE on a table with an AUTO_INCREMENT field, we can get the ID of the last inserted/updated record immediately: $last_id = $conn->insert_id;

Mijn testcode wordt dan :
$db = openDB(); // OO-functie de db-connectie afhandelt, werkt foutloos
if ($pid === 9999) $p = $db->query($qInsert); // zonder pid
else $p = $db->query($qUpdate); // met de optie WHERE pid='$pid'

$pid = $db->insert_id; // ZOU in allebei de gevallen de laatste AI-waarde moeten geven ?

$db->close();
print $pid; // geeft 0 dus waarschijnlijk NULL

Heeft iemand enig idee wat ik fout doe?
Je weet dat na 9998 inserts er een record gaat komen met id 9999?

Waarom dan niet $id = null
Ben van Velzen op 18/09/2016 21:25:00

Ehm nee, niet doen. Je kan er niet vanuit gaan dat je dan het juiste id krijgt. De enige correcte manier na een insert is insert_id gebruiken, en bij een update weet je deze al.

Helemaal mee eens. Als het misgaat is dit bovendien een draak van een bug om op te sporen. Het kan misgaan als twee verschillende clients tegelijkertijd een record invoegen. In plaats van het id van het record dat je zelf invoegde, kun je dan het id van de andere client krijgen. Veel plezier met het uitzoeken waarom meneer Jansen ineens van Lelystad naar Delfzijl is verhuisd. ;-)

Wat je wel zou kunnen doen is een SELECT LAST_INSERT_ID(). Die geeft het id van het laatst ingevoegde id voor de betreffende db-connectie en heeft dus geen last van concurrent inserts.
Paul Ulje op 18/09/2016 19:44:07

if ($pid === 9999)

Paul Ulje op 18/09/2016 20:15:52

09999

Paul Ulje op 18/09/2016 20:43:03

09999Gewoon nul

09999 !== 9999
Ik geloof dat ik met mijn slordige voorbeeld de discussie wat in de war heb gestuurd. Let niet op de 9999, die heeft er niks mee te maken, die was er alleen in de test. En 09999 bestaat uit twee print resultaten. Dus daar is geen vergelijk met de string 9999 van toepassing.

De functie getMaxID() is een OMWEG voor het FALENDE insert_id, de oorzaak van deze draad.

De door MySQL doorgenummerde A_I nummers komen in een veld genaamd ID.
- Wanneer een nieuw record wordt ingevoegd komt er dus een nieuw ID. Dát nummer wil ik weten.


<?php
function getMaxAI() {
$db = openDB();
$p = $db->query(" select * from naw order by id desc ");
$row = $p->fetch_row();
$id=$row[0];
$db->close();
return $id;
}
?>


En dat werkt naar volle tevredenheid.

[size=xsmall]Toevoeging op 19/09/2016 14:23:29:[/size]

Ivo P op 19/09/2016 00:22:18

Je weet dat na 9998 inserts er een record gaat komen met id 9999?

Waarom dan niet $id = null



:-) Ja, dat is een restant uit de jaren 70-80 toen '9' en '99' e.d. standaard de 'afsluit' codes waren. Let wel, er waren nog geen knoppen, geen muis, alleen een toetsenbord. Ik zal het veranderen.... Bedankt!

Het gaat fout zodra je dit met meer dan één client online doet:

1. Client A haalt de hoogste id op.
2. Client B voegt een record toe en verhoogt de id.
3. Client A werkt met een verouderde hoogste id.

Verder vraagt je query nu de gehele tabel op. Dit kun je beperken tot de id van de laatste record:

SELECT id FROM naw ORDER BY id DESC LIMIT 1
>> De functie getMaxID() is een OMWEG voor het FALENDE insert_id, de oorzaak van deze draad.
En dat terwijl de oorzaak gewoon ergens foutief gebruik is. Zoals gezegd: je gebruikt insert_id vlak na je INSERT query, bij UPDATE e.d. weet je het ID al, dus heb je dit niet nodig. Daarnaast zijn er *geen* omwegen voor insert_id, ja, hooguit binnen een transactie je complete table locken, inserten en *dan* opvragen. Maakt je applicatie wel retetraag uiteraard omdat je dan alle andere toegangen tot de table verbiedt. Kort gezegd: wat je doet werkt niet en kan ook niet werken.
TL;DR Het nummertjesapparaat van MySQL zelf werkt goed zat, bouw hier geen eigen apparaat voor.

getMaxID() lijkt mij niet de juiste weg. Jouw database heeft zelf oneindig veel betere functionaliteit om zelf te bepalen welk auto-increment id deze moet toewijzen aan een nieuw record.

En wat @Ward zegt: op het moment dat twee verschillende gebruikers "tegelijkertijd" iets met getMaxID() doen ben je nat. Tenzij je doet wat @Ben voorstelt: iets met transacties, maar dat is voortborduren op een verkeerde ontwerpbeslissing.
Helemaal met je eens Thomas.
Uiteraard maak ik graag gebruik van MySql A_I en dat werkt probleemloos.

Mijn programma is een eeuwenoud privé programma, waarschijnlijk heb ik het oorspronkelijk in dBase en vervolgens in Clipper gemaakt. Na de omzetting in PHP, vermoedelijk om PHP 'te proeven' jarenlang over het Web ongestoord gebruikt.

Nu wil ik alleen direct na het TOEgevoegen het 'id'-nummer dat automagisch is toegevoegd gebruiken (uitlezen, niet toevoegen). En dat lukt me niet met insert_id.

Dan maar eromheen.
Er is (bijna) altijd een omweg.
In dit geval eigenlijk heel eenvoudig.
(Vroeguh, toen er nog geen DB voor de voor-PC was, moesten we altijd zelf een 'nummertjesapparaat' bouwen).
Maar terecht gezegd: niet elegant.
En elegantie (Pascal!) is voor mij belangrijk. :-(
In de beginjaren van IBM/MSDos deed ik overigens weinig anders dan omwegen verzinnen voor de gebreken.

Een ieder hartelijk bedankt voor de goede raad en steun!
Ik voel me helemaal thuis in dit forum.
Nu snel een nieuw PHP probleem zoeken.... :-)
Paul Ulje op 21/09/2016 15:08:59

Dan maar eromheen.
Er is (bijna) altijd een omweg.
In dit geval eigenlijk heel eenvoudig.

Inderdaad eenvoudig: SELECT LAST_INSERT_ID(). Maar absoluut niet "select * [...] order by id desc" want vroeg of laat ga je daarmee een keer de bietenbrug op. En het erge is dat je dat vaak nog niet eens merkt tot het te laat is om de boel te herstellen. Het enige wat je dan nog kan doen is je hele database weggooien en overnieuw beginnen.

Er is bijna altijd een omweg, correct. Maar die omweg hangt wel af van je begrip van waar je mee werkt. Een oplossing zoals je probeerde duidt duidelijk op een onbegrip, gezien de race conditions die je daar altijd mee veroorzaakt. Je kunt dan de omweg van Willem beter gebruiken, of zoals eerder gezegd je code herzien zodat je alleen het id uit de database vraagt bij een insert.

Reageren