Toon posts:

[Alg] methodes om ID te verkrijgen voor een insert

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik het kort zie je hier vaak de vraag 'hoe verkrijg ik een id voor mijn geinserte record' voorbij komen.

Vaak wordt daar een antwoord op gegeven in de trand van 'select max(id) from table'.

Nu is er mij altijd geleerd dat dat de foute manier is om het te doen, maar ik krijg de indruk dat de heersende mening hier is dat dit niet zo is.

Het lijkt mij dat je hiervoor het liefst een generator gebruikt (indien aanwezig in je database), of een autoinc veldje indien aanwezig.

Stel nu dat je database dit niet heeft. Hoe kun je dit dan het beste aanpakken?

Ik zat zelf te denken aan een apart tabelletje met ID's, waaruit je applicatie een ID haalt en dan het huidige ID ophoogt. Eigenlijk hetzelfde dus als een generator, maar dan zelf geimplementeerd ipv. dat je database het bijhoudt. Is dat de juiste methode, of zijn er betere/handiger methodes?

Verwijderd

Indien het ID nergens anders voor gebruikt wordt, kan je in principe sequences gebruiken (door de db gegenereerde nummers), echter gebruiken veel ontwikkelaars ID's ook als bv. factuurnr etc.. Probleem met sequences is vaak dat ze niet in een rollback schema worden meegenomen, in het geval van factuurnr's krijg je dan 'gaten' in je nummering, wat weer niet mag van sommige instanties (en overigens ook niet wenselijk is).

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Mja je kunt wel een complete tabel voor writeacties gaan locken voor je het hoogste ID op gaat halen en daarna die gaat gebruiken om toe te voegen in je DB.

  • Blizard
  • Registratie: September 2001
  • Niet online
Inderdaad is er het "probleem" van gaten bij de nummering. Dan moet je echter zelf uitmaken of deze wenselijk zijn, dan niet. Bij facturen heb je inderdaad niet graag (mag zelfs niet) dat bij een clear van de database er gewoon opnieuw nummering begint vanaf 0.

Maar als je nou gewoon bonnetjes wil uitdelen op een fuif en op een volgende fuif wil je dit weer doen, clear je gewoon de database (tabel) en heb je er geen probleem mee dat hij opnieuw begint bij 0.

Bij de eerste methode is je eigen voorstel zo slecht nog niet. Gewoon een tabel met één waarde in (laatste factuur-nr)

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
Indien het een autonummering-column betreft, dan heeft een DBMS daar wel een functie of een variable voor (@@identity, scope_identity(), en ident_current() in SQL Server), of in het geval van Oracle kan je daar met Sequences werken: daarbij ga je eerst het id gaan genereren, en dan pas het record inserten.
Bij SQL Server werkt het anders: eerst het record inserten, en dan het id opvragen van dat record.

Indien je DB geen autoincrement columns heeft, dan maak je best een tabel aan met 2 columns: 1 column waarin je de naam van de tabel opslaat, en 1 column met de laatste of de eerstvolgende waarde voor de PK van die tabel.
Bij het maken van een record lock je die tabel of dat record dan, bepaal je het nieuwe id, verhoog je het id in die 'hulp-tabel', en geef je je lock weer vrij.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
Blizard schreef op 09 juli 2004 @ 18:44:
Inderdaad is er het "probleem" van gaten bij de nummering. Dan moet je echter zelf uitmaken of deze wenselijk zijn, dan niet. Bij facturen heb je inderdaad niet graag (mag zelfs niet) dat bij een clear van de database er gewoon opnieuw nummering begint vanaf 0.
Daar moet je dan ook geen auto-incr. field voor gebruiken.
Auto-incr. fields zijn er imo enkel en alleen voor PK's. En een PK zou geen enkele betekenis/waarde mogen hebben voor dat record zelf; maw, je PK mag geen natural key zijn.

https://fgheysels.github.io/


Verwijderd

whoami schreef op 09 juli 2004 @ 18:45:
[...]
Daar moet je dan ook geen auto-incr. field voor gebruiken.
Auto-incr. fields zijn er imo enkel en alleen voor PK's. En een PK zou geen enkele betekenis/waarde mogen hebben voor dat record zelf; maw, je PK mag geen natural key zijn.
Klopt, maar je komt helaas nogal eens anders tegen.
Ik maak zelf meestal een ID tabel waarin de ID's worden opgeslagen, hierin zitten oa. ID_Naam (bv. FactuurId) , ID_Waarde (laatste waarde), ID_Layout (een mask voor het id), via 1 routine kan ik dan voor iedere willekeurige tabel een ID opvragen.

[ Voor 30% gewijzigd door Verwijderd op 09-07-2004 18:52 ]


  • KrL
  • Registratie: Oktober 2001
  • Laatst online: 12-05 21:39

KrL

Doe maar duurzaam..

Select max(id) from table is idd fout.. Stel dat je een record met het hoogste ID (100) verwijdert en daarna opnieuw een record toevoegt dan krijg deze ID 101 terwijl je max(id) dan 99 is..

Een manier om de auto_inc waarde te vinden een 'show table status from DBNAAM like 'tablenaam' te doen.. De waarde 'Auto_increment' die je dan terugkrijgt is de waarde die je wilt hebben..

[ Voor 6% gewijzigd door KrL op 09-07-2004 18:51 . Reden: Dit geldt dus voor MySQL ! ]


Verwijderd

wat ik doe is zelf id's maken op basis van de timestamp met een random toevoeging van 3 char's. Zo is het uniek en heb je altijd meteen je id omdat je die zelf genereert.

heb je ook geen problemen als je ooit wilt synchorniseren ofzo..

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
KrL schreef op 09 juli 2004 @ 18:50:
Select max(id) from table is idd fout.. Stel dat je een record met het hoogste ID (stel 100) verwijdert en daarna opnieuw een record toevoegt dan krijg deze ID 101 terwijl je max(id) dan 99 is..

Een manier om de auto_inc waarde te vinden een 'show table status from DBNAAM like 'tablenaam' te doen.. De waarde 'Auto_increment' die je dan terugkrijgt is de waarde die je wilt hebben..
Als je een auto-incr field hebt, dan doe je gewoon een insert zonder dat je een waarde meegeeft voor dat veld, en de DB zal zelf wel de juiste waarde geven.
Het enige wat je dan nog hoeft te doen, is achteraf het juiste id ophalen dmv de functies die het DBMS ter beschikking stelt.
IMO is het zelfs best als je geen explictie inserts toelaat op auto-incr velden (SET IDENTITY_INSERT OFF in SQL Server).

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
Verwijderd schreef op 09 juli 2004 @ 18:50:
wat ik doe is zelf id's maken op basis van de timestamp met een random toevoeging van 3 char's. Zo is het uniek en heb je altijd meteen je id omdat je die zelf genereert.

heb je ook geen problemen als je ooit wilt synchorniseren ofzo..
Waarom gebruik je dan geen GUID 's ipv zelf moeilijk te gaan doen, en ID's te genereren? :?

https://fgheysels.github.io/


Verwijderd

whoami schreef op 09 juli 2004 @ 18:53:
[...]
Waarom gebruik je dan geen GUID 's ipv zelf moeilijk te gaan doen, en ID's te genereren? :?
Die heb je ook niet overal ter beschikking ('t leven bestaan niet alleen uit ms-sql/oracle)

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
Verwijderd schreef op 09 juli 2004 @ 18:56:
[...]

Die heb je ook niet overal ter beschikking ('t leven bestaan niet alleen uit ms-sql/oracle)
Hmm, in vrijwel ieder DBMS dat ik ken, heb je zoiets als een GUID.

https://fgheysels.github.io/


Verwijderd

whoami schreef op 09 juli 2004 @ 18:59:
[...]
Hmm, in vrijwel ieder DBMS dat ik ken, heb je zoiets als een GUID.
Dan ken je nog niet ieder DBMS :) (progress bijvoorbeeld heeft geen guid's )

[ Voor 5% gewijzigd door Verwijderd op 09-07-2004 19:02 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 22:18
Dat beweer ik ook niet. :)

https://fgheysels.github.io/


Verwijderd

Topicstarter
Verwijderd schreef op 09 juli 2004 @ 18:50:
wat ik doe is zelf id's maken op basis van de timestamp met een random toevoeging van 3 char's. Zo is het uniek en heb je altijd meteen je id omdat je die zelf genereert.

heb je ook geen problemen als je ooit wilt synchorniseren ofzo..
Vind het een vrij ranzige methode eigenlijk, komt op hetzelfde neer als select max (); je hebt geen 100% garantie dat je ID's uniek zijn. Het is theoretisch mogelijk dat je dezelfde ID meerdere keren maakt (in een multi-user applicatie) en dat wil je juist niet.

Voor de rest zie ik autoinc velden, sequencers, generators.. allemaal DBMS functies, wat als je DB nu eens niet over die functies beschikt? Daar ging het mij nl meer om :P

(plus: een ID met chars erin?)

[ Voor 4% gewijzigd door Verwijderd op 09-07-2004 19:48 ]


  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

Een id dient in principe ter unieke identificatie.
Ik gebruik er altijd sequences voor.

Zodra je id's van chars in elkaar gaat zetten of je zorgen maakt over gaten in je nummering dan moet je een hele bijzondere reden hebben.
Hierdoor krijgt je veld namelijk meer functies dan alleen identificeren.
Het is dan handiger om van zo'n veld een unique key te maken naast de primary key.

Who is John Galt?


  • MisterData
  • Registratie: September 2001
  • Laatst online: 16-05 23:29
In mysql gewoon LAST_INSERT_ID hoor?

  • faabman
  • Registratie: Januari 2001
  • Laatst online: 08-08-2024
Verwijderd schreef op 09 juli 2004 @ 19:01:
[...]

Dan ken je nog niet ieder DBMS :) (progress bijvoorbeeld heeft geen guid's )
Je hoeft je GUID toch ook niet aan te maken met je DBMS?? Kun je ook aan de applicatiekant doen...

Op zoek naar een baan als Coldfusion webdeveloper? Mail me!


Verwijderd

Verwijderd schreef op 09 juli 2004 @ 19:48:
[...]

(plus: een ID met chars erin?)
ja daarom juist ook wat [A-Z] [a-z] erin, omdat er een kleine kans is dat meerdere gebruikers de zelfde microseconden gebruiken als primairy key. Er nog wat random gegevens (zoals 3 letters) aan vastplakken maakt die kans zowat nihil..

zo wie zo gebruik je een methode om id's te generaten voor meerdere tabellen enz.. en die kans word daardoor alleen maar kleiner..

ranzig vind ik het niet echt, maar dat is verschil van mening : ) ik wil het namelijk ook in de toekomst gebruiken om gegevens uit verschillende database's (met de zelfde structuur) te mergen. Dit kan mooi als ik zeker weet dat alle id's niet gelijk kunnen zijn.

[ Voor 37% gewijzigd door Verwijderd op 10-07-2004 10:31 ]


  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 10:34
In mysql gebruik ik eigenlijk 2 methoden om het id op te vragen van een zojuist ingevoerde rij. Gaat het om een database waar weinig kans is dat er meerdere gebruikers tegelijk iets invoeren (achterkant van een CMS ofzo) dan gebruik ik mysql_insert_id().

Is de kans groter dat er concurrent users bezig zijn dan select hem op basis van de ingevoerde gegevens:
code:
1
SELECT id FROM table WHERE columns = 'values' ORDER BY id DESC LIMIT 1

Dat gaat alleen mis als 2 users ongeveer tegelijk precies dezelfde gegevens invoeren (=kans nihil).

Regeren is vooruitschuiven


  • Marijn_S
  • Registratie: Februari 2001
  • Niet online
T-MOB schreef op 10 juli 2004 @ 11:10:
In mysql gebruik ik eigenlijk 2 methoden om het id op te vragen van een zojuist ingevoerde rij. Gaat het om een database waar weinig kans is dat er meerdere gebruikers tegelijk iets invoeren (achterkant van een CMS ofzo) dan gebruik ik mysql_insert_id().

Is de kans groter dat er concurrent users bezig zijn dan select hem op basis van de ingevoerde gegevens:
code:
1
SELECT id FROM table WHERE columns = 'values' ORDER BY id DESC LIMIT 1

Dat gaat alleen mis als 2 users ongeveer tegelijk precies dezelfde gegevens invoeren (=kans nihil).
Ik zie niet echt in waarom je nou die 2e manier gebruikt als er meerdere gebruikers bezig kunnen zijn, die lijkt me zeker niet veiliger in gebruik dan de eerste.

Verder is de kans misschien vrij klein als er weinig gebruikers zijn, maar hoe meer gebruikers, hoe groter de kans (toch?). En dan is die kans misschien nog steeds klein, maar hij is er wel! En corrupte data / foute verwijzingen hierdoor is echt geen pretje :)

System specs - Ik word blij van knipperende lichtjes.


Verwijderd

Het is wel ranzig maar eeuh, ik veronderstel dat je toch een of ander uniek veld opslaat (bv een username), dan kan je daarna toch gewoon select * from blabla where Username='de username' doen?
(gewoon een gedacht, er zijn namelijk bestaande functies hiervoor (en ik dacht dat dit in .net al makkelijker ging dan in gewoon asp (of vb6 ofzo))

Verwijderd

T-MOB schreef op 10 juli 2004 @ 11:10:
In mysql gebruik ik eigenlijk 2 methoden om het id op te vragen van een zojuist ingevoerde rij. Gaat het om een database waar weinig kans is dat er meerdere gebruikers tegelijk iets invoeren (achterkant van een CMS ofzo) dan gebruik ik mysql_insert_id().

Is de kans groter dat er concurrent users bezig zijn dan select hem op basis van de ingevoerde gegevens:
code:
1
SELECT id FROM table WHERE columns = 'values' ORDER BY id DESC LIMIT 1

Dat gaat alleen mis als 2 users ongeveer tegelijk precies dezelfde gegevens invoeren (=kans nihil).
kans nihil, betekent kans, dus kan (MOET) je er vanuit gaan dat de situatie zich ooit zal voordoen.

Verwijderd

T-MOB schreef op 10 juli 2004 @ 11:10:
In mysql gebruik ik eigenlijk 2 methoden om het id op te vragen van een zojuist ingevoerde rij. Gaat het om een database waar weinig kans is dat er meerdere gebruikers tegelijk iets invoeren (achterkant van een CMS ofzo) dan gebruik ik mysql_insert_id().

Is de kans groter dat er concurrent users bezig zijn dan select hem op basis van de ingevoerde gegevens:
code:
1
SELECT id FROM table WHERE columns = 'values' ORDER BY id DESC LIMIT 1

Dat gaat alleen mis als 2 users ongeveer tegelijk precies dezelfde gegevens invoeren (=kans nihil).
Niet erg handig, kijk nog eens naar de werking van mysql_insert_id() zou ik zeggen. Deze functie retourneert het id van de laatste insert van de laatst geopende verbinding (van het draaiende script). Als je dus in een omgeving met meerdere users werkt gaat dit nog steeds goed, terwijl je tweede optie een kleine kans van falen heeft.

[ Voor 3% gewijzigd door Verwijderd op 10-07-2004 12:17 ]


  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 10:34
* T-MOB voelt zich spuit 11 8)7

Afijn weer wat geleerd \0/.
Overigens blijft de kans op fouten met methode 2 kleiner dan wanneer je id's met random strings gebruikt. Zeker met complexe invoer.

[ Voor 4% gewijzigd door T-MOB op 10-07-2004 12:49 ]

Regeren is vooruitschuiven


Verwijderd

Topicstarter
Verwijderd schreef op 10 juli 2004 @ 10:25:
ranzig vind ik het niet echt, maar dat is verschil van mening : ) ik wil het namelijk ook in de toekomst gebruiken om gegevens uit verschillende database's (met de zelfde structuur) te mergen. Dit kan mooi als ik zeker weet dat alle id's niet gelijk kunnen zijn.
Ik denk toch dat de algemene mening is dat chars in je ID velden frotten best wel smerig is.

Daarnaast kan ik me indeken dat het niet goed is voor je performance, een integer veld lijkt mij makkelijker (sneller) te sorteren en te benaderen dan een varchar.

Verwijderd

Verwijderd schreef op 10 juli 2004 @ 13:42:
[...]


Ik denk toch dat de algemene mening is dat chars in je ID velden frotten best wel smerig is.

Daarnaast kan ik me indeken dat het niet goed is voor je performance, een integer veld lijkt mij makkelijker (sneller) te sorteren en te benaderen dan een varchar.
vraag me af of dat argument klopt? of een selectie op een int 10 sneller is dan een varchar 10 : ) moeten we maar eens benchmarken : )
Pagina: 1