[PHP & MySQL] nieuwste id terugontvangen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Hallo,

ik ben op dit moment bezig met een query waarbij er meerdere rijen tegelijk in een tabel worden gestopt. Dit zullen ongeveer 250 rijen in één query zijn.

Nu wil ik het laatst aangemaakte id terug krijgen ( autoincrement ), maar nog liever wil ik alle id's terugkrijgen.

Maar zowel de functie:
mysql_insert_id() als
PHP:
1
2
3
4
$nieuwIdR = mysql_query( "SELECT LAST_INSERT_ID()" ) or die("Er is een fout opgetreden: ".mysql_error());//selecteer het laatste id
                    $nieuwId = 0;
                    if($newIdR = mysql_fetch_row($nieuwIdR))
                        $nieuwId = $newIdR[0];


Geven niet het hoogste (en mijn inziens dus laatste) id, maar het eerste id terug.
Dus als ik 250 rijen insert krijg ik, i.p.v. 250, 1 terug.

Zo ziet mijn query eruit (ingekort):
PHP:
1
2
INSERT INTO werkplaats (id, land, postcode, plaats) 
VALUES (NULL, 'NED', '1234 AA', 'Amsterdam'), (NULL, 'NED', '1434 ZZ', 'Rotterdam');


Weet iemand hoe dit kan?

Of heeft iemand een idee hoe ik alle zojuist aangemaakte id's kan terugkrijgen?
Want nu probeer ik met het aantal ingevoerde rijen (mysql_affected_rows()) en het laatste id, alle id's terug te toveren.
Dit levert geen grote problemen op omdat er tussen het invoeren en het ophalen nog geen rijen verwijderd kunnen worden, maar netjes is het natuurlijk niet. Ook omdat je (in theorie) nooit zeker weet of mysql wel opeen volgende nummers gebruikt.

Ook lijkt het mij bij zulke aantallen niet verstandig om elke rij apart te inserten en dan per rij het id op te vragen.

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 16:06

MBV

Volgens mij werkt het alleen als je 1 query per keer doet. Als je een query verzint die 500 dingen toevoegt in 1x zal dat dus niet werken.

Wat gebeurt er trouwens in PHPMyAdmin?

Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Wat bedoel je precies met wat gebeurt er in phpMyAdmin?
Als ik daarmee de tabel bekijk, staan ze er gewoon van 1 tot 250 (bijvoorbeeld) in.

Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 06-06 09:54
Eerst een insert-statement, en daarna (in dezelfde pagina, tijdens dezelfde verbinding:
SQL:
1
SELECT LAST_INSERT_ID();


Voorbeeld
PHP:
1
2
3
4
// PEAR::DB
$db->query('INSERT INTO tabel (veld, veld2) VALUES ("waarde1","waarde2")');
// Laatste ID:
echo $db->getOne('SELECT LAST_INSERT_ID()');

[ Voor 99% gewijzigd door Skaah op 11-01-2006 16:08 ]


Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Skaah schreef op woensdag 11 januari 2006 @ 16:05:
Eerst een insert-statement, en daarna (in dezelfde pagina, tijdens dezelfde verbinding:
SQL:
1
SELECT LAST_INSERT_ID()
Zoals ik in de startpost had aangegeven werkt deze methode helaas ook niet.

edit: je hebt hem aangepast zie ik, maar ik gebruik geen PEAR

[ Voor 34% gewijzigd door Anoniem: 64033 op 11-01-2006 16:09 ]


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 17-06 22:41

TeeDee

CQB 241

Kan mySql omgaan met @@SELECT IDENTITY, @@SCOPE_IDENTITY etc. etc.?

Dan zou je zoiets kunnen doen:
code:
1
insert into blaat (woei, melp) values(1,2);@@SELECT IDENTITY

Je result bevat dan deze ident.

Edit:
Ik snap 'm nu. Je voert 250 rijen in, in 1 query, maar per rij wil je de id hebben.
Tja, dan lijkt me dat je dynamisch 250 query's moet bouwen, iedere de @@IDENTITY terughalen, en die in een Array stoppen ofzo.

[ Voor 35% gewijzigd door TeeDee op 11-01-2006 16:17 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 06-06 09:54
Anoniem: 64033 schreef op woensdag 11 januari 2006 @ 16:08:
[...]
Zoals ik in de startpost had aangegeven werkt deze methode helaas ook niet.
Pardon, ik las het niet goed. Je hebt één query waarmee je meerdere rijen toevoegd? Dus...
SQL:
1
2
3
INSERT INTO tabel (veld1, veld2) VALUES
("waarde1","waarde2"),
("waarde3","waarde4"));

? Voor zover ik weet kan het dan niet. Dan zou je alle queries apart moeten invoeren.

edit:

Je hoeft geen PEAR te hebben. Het enige wat belangrijk is, is dat je het op dezelfde pagina doet. Het werkt namelijk per connectie.

[ Voor 18% gewijzigd door Skaah op 11-01-2006 16:12 ]


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

PHP:
1
mysql_query("SELECT * FROM tabel ORDER BY id LIMIT 1");


gaat dit niet?

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Sybr_E-N
  • Registratie: December 2001
  • Laatst online: 16-06 22:46
snake903 schreef op woensdag 11 januari 2006 @ 16:13:
PHP:
1
mysql_query("SELECT * FROM tabel ORDER BY id LIMIT 1");


gaat dit niet?
Dat wil de TS helemaal niet.

De TS wil nadat er een X aantal row's zijn toegevoegd, van die X row's de door de database gegenereerde ID (primary key auto_increment) waarden terug.

Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
snake903 schreef op woensdag 11 januari 2006 @ 16:13:
PHP:
1
mysql_query("SELECT * FROM tabel ORDER BY id LIMIT 1");


gaat dit niet?
Dit werkt, netjes vind ik het eigenlijk niet, maar dat is beter dan andere geknutselde oplossingen.

@ Skaah: ik heb inderdaad een query waarbij ik meerdere rijen tegelijk INSERT.

Maar eigenlijk heb ik liever alle nieuwe id's terug.
Zoals Sybr_E-N dus ook aangeeft.

Maar zoals ik al zei, heb ik er geen behoefte aan om alle rijen apart te inserten en dan de id's apart op te slaan. Waarbij ik ze ook al niet in een array kan opslaan, omdat het er mogelijk meer dan 512 (volgens mij, of is dat alleen in andere programmeertalen zo? ) kunnen zijn.

[ Voor 3% gewijzigd door Anoniem: 64033 op 11-01-2006 16:20 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 19:22

Creepy

Tactical Espionage Splatterer

Een array kan echt wel groter worden dan 512 hoor ;)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Creepy schreef op woensdag 11 januari 2006 @ 16:22:
Een array kan echt wel groter worden dan 512 hoor ;)
Hoe groot kan een array dan worden?

Maar desondanks veranderd dat nog niets aan mijn standpunt dat ik ook vanuit het efficiencyaspect liever 1 query doe, dan 250+ losse query’s.

Acties:
  • 0 Henk 'm!

  • PiweD
  • Registratie: Augustus 2004
  • Niet online

PiweD

Redacteur
Anoniem: 64033 schreef op woensdag 11 januari 2006 @ 16:28:
[...]

Hoe groot kan een array dan worden?

Maar desondanks veranderd dat nog niets aan mijn standpunt dat ik ook vanuit het efficiencyaspect liever 1 query doe, dan 250+ losse query’s.
PHP:
1
2
3
4
5
6
7
8
9
10
11
<?

$query = mysql_query("SELECT `id` FROM `werkplaats` ORDER BY `id` DESC LIMIT 1");

$laatste_id = mysql_result($query,0,'id');

//hier al je ubergrote insert query's....

$query = mysql_query("SELECT `id` FROM `werkplaats` WHERE `id` > '" . $laatste_id . "'");

?>

so·wie·so (bijwoord) - 1 hoe dan ook


Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Dat is inderdaad de oplossing.
Nu is het zelfs mogelijk om met mysql_fetch_row() door de nieuwe id's heen te lopen.

Hartelijk dank hiervoor.

Waarom heb ik dit zelf niet verzonnen 8)7

Acties:
  • 0 Henk 'm!

  • Skaah
  • Registratie: Juni 2001
  • Laatst online: 06-06 09:54
Anoniem: 64033 schreef op woensdag 11 januari 2006 @ 16:54:
Dat is inderdaad de oplossing.
Nu is het zelfs mogelijk om met mysql_fetch_row() door de nieuwe id's heen te lopen.

Hartelijk dank hiervoor.

Waarom heb ik dit zelf niet verzonnen 8)7
Als er nu tijdens je mega-insert nog een mega-insert is, is alles mooi verneukt. Je zou nog een LOCK TABLE en UNLOCK table toe kunnen voegen, voor de zekerheid.

Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Skaah schreef op woensdag 11 januari 2006 @ 17:07:
[...]

Als er nu tijdens je mega-insert nog een mega-insert is, is alles mooi verneukt. Je zou nog een LOCK TABLE en UNLOCK table toe kunnen voegen, voor de zekerheid.
Oei, daar had ik nog niet aangedacht.

Maar de kans is heel klein dat dit gebeurt, omdat het een beheerdersscherm is.
In theorie is er dus kans dat het gebeurt, in de praktijk eigenlijk niet.

Maar als er een mooiere / betere oplossing is, houd ik me aanbevolen.

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 09-06 21:17
Err ik neem aan dat je die insert query dynamisch opbouwt? Dan weet je dus ook hoeveel inserts je gaat doen.
mysql_insert_id() + het aantal toegevoegde waardes, dan weet je het laagste en hoogste nieuwe ID. For-loopje erbij en je kunt alle ID's af?

Of een unieke key verzinnen welke je mee insert, en vervolgens alle records selecteren met die unieke key. Dan loopt het oko niet de soep in als er 2 inserts door elkaar lopen.

Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
frickY schreef op woensdag 11 januari 2006 @ 17:17:
Err ik neem aan dat je die insert query dynamisch opbouwt? Dan weet je dus ook hoeveel inserts je gaat doen.
mysql_insert_id() + het aantal toegevoegde waardes, dan weet je het laagste en hoogste nieuwe ID. For-loopje erbij en je kunt alle ID's af?

Of een unieke key verzinnen welke je mee insert, en vervolgens alle records selecteren met die unieke key. Dan loopt het oko niet de soep in als er 2 inserts door elkaar lopen.
Ja, je zou met mysql_affected_rows() het aantal geinserte rijen kunnen bepalen.

Maar zoals ik al eerder zei kun je er in mysql vanuit gaan dat de id's op volgorde gesorteerd zijn, maar dat hoeft natuurlijk niet, het kan zijn dat iemand anders toevallig op hetzelfde moment ook aan het inserten is (hetzelfde probleem als hierboven dus).
Ook kan het zijn dat mysql ineens iets anders bedenkt, bijvoorbeeld alleen even nummers ;).

Dat unieke id is dan nog een leuke oplossing, bijvoorbeeld een timestamp oid, maar je gaat dat ook extra opslaan in de database, en dat vind ik wel weer zonde.
Het liefst houd je natuurlijk de inhoud gescheiden van de techniek.

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 16:06

MBV

Anoniem: 64033 schreef op woensdag 11 januari 2006 @ 17:12:
[...]

Oei, daar had ik nog niet aangedacht.

Maar de kans is heel klein dat dit gebeurt, omdat het een beheerdersscherm is.
In theorie is er dus kans dat het gebeurt, in de praktijk eigenlijk niet.

Maar als er een mooiere / betere oplossing is, houd ik me aanbevolen.
Met een LOCK/UNLOCK is deze veilig :)

Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Ja, ik heb het nu als volgt:

PHP:
1
2
3
4
5
6
7
8
9
10
11
$selLI = mysql_query("SELECT id FROM `werkplaats` ORDER BY `id` DESC LIMIT 1"); 
if(mysql_num_rows($selLI)>0)
    $laatste_id = mysql_result($selLI,0,'id');//het hoogste id, voor het inserten.
mysql_query("LOCK TABLES werkplaats WRITE");

$insQ = "INSERT INTO werkplaats ...Mijn mega query";
$insR = mysql_query($insQ) or die("Het invoeren van de werkplaatsen is mislukt: ".mysql_error());
mysql_query("UNLOCK TABLES");

$selNIQ = "SELECT id FROM `werkplaats` WHERE `id` > '" . $laatste_id. "';";
$selNIR = mysql_query($selNIQ) or die("Er is een fout opgetreden: ".mysql_error());

Wat ik me afvraag is of ik de LOCKTABLES niet na de SELECT id FROM 'werkplaats'.. moet doen.
Want het zou in theorie mogelijk zijn dat iemand tussen die 2 statements in nog een insert doet.

[ Voor 20% gewijzigd door Anoniem: 64033 op 12-01-2006 10:06 . Reden: typo's ]


Acties:
  • 0 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Wordt de lock gereleased nadat je een die(...) hebt gedaan? Ik heb geen ervaring met locking in MySQL, maar in ORACLE heb je kans dat je lock blijft staan. Dus ik zou de foutafhandeling van je query iets subtieler maken. Met andere woorden: na een fout in je inserts zou ik de tabel eerst releasen.

When life gives you lemons, start a battery factory


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 17-06 17:33

Janoz

Moderator Devschuur®

!litemod

Ten eerste zou ik de LOCK UNLOCK na de select doen. Op dit moment kan er nog steeds een insert tussendoor vliegen.

Daarnaast zou ik idd in de die's ook nog even wat opruim werk doen. Zodra er iets fout gaat bij de insert blijft je tabel gelocked.

[ Voor 3% gewijzigd door Janoz op 12-01-2006 11:03 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

Anoniem: 64033

Topicstarter
Janoz schreef op donderdag 12 januari 2006 @ 10:24:
Ten eerste zou ik de LOCK na de select doen. Op dit moment kan er nog steeds een insert tussendoor vliegen.

Daarnaast zou ik idd in de die's ook nog even wat opruim werk doen. Zodra er iets fout gaat bij de insert blijft je tabel gelocked.
Ik doe de LOCK toch na de select?

Maar ik heb na de UNLOCK nog een controle via mysql_affected_rows(), en daar komt 0 uit i.p.v. de 250. Deze 250 rijen zijn echter wel in de database ingevoegd als ik dat via phpMyAdmin bekijk.

En wat zou ik dan aan de die() moeten aanpassen om de tabel toch wel weer vrij te geven?

[ Voor 1% gewijzigd door Anoniem: 64033 op 12-01-2006 10:33 . Reden: Moet nog wakker worden ]


Acties:
  • 0 Henk 'm!

  • Tijsje
  • Registratie: Februari 2001
  • Laatst online: 13:50
Waarom maak je er toch niet gewoon losse insert querys van?
Is waarschijnlijk net zo efficient als daarna weer alles op gaan halen.
En als er dan een insert statement fout gaat weet je ook meteen welke dat is.

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 16:06

MBV

Je moet de LOCK volgens mij vóór de select doen, en de UNLOCK zodra je óveral mee klaar bent. Als er ergens daar tussenin iets gebeurd, kan je verloren zijn, theoretisch.

mysql_affected_rows kijkt naar de laatste query. Bij een UNLOCK zijn er 0 affected :)

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Je 'critical region' (set niet-atomaire acties die je wel als dusdanig wil uitvoeren) is incl. beide selects, dus de LOCK/UNLOCK moet daar gewoon helemaal omheen.

{signature}

Pagina: 1