Toon posts:

[Database(s)] Waarom maar èèn autonummeringsveld per tabel?

Pagina: 1
Acties:
  • 159 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
In databases, of in ieder geval MSSQLserver, kun je maar 1 autonummeringsveld per tabel aanmaken. Waarom is dit? Deze vraag in verband met een applicatie die ik aan het maken ben waarin ik in een soortgelijk systeem ook wellicht meerdere autonummeringsvelden wil toestaan. Mocht de database reden een goede reden zijn, dan zou ik dit kunnen limiteren op 1 autonummeringsveld (in mijn systeem dus).

Kortom: Kan iemand me vertellen waarom dit zo is in een database tabel?

  • Creepy
  • Registratie: Juni 2001
  • Nu online

Creepy

Tactical Espionage Splatterer

Dan krijg je twee keer hetzelfde nummer in de tabel, lijkt me niet echt handig :P

"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


  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 13:59

Nick_S

++?????++ Out of Cheese Error

Ik kan me zo voorstellen, dat als je meerdere autonumber velden hebt, deze allemaal elke keer dezelfde waarde krijgen. Lijkt me dus overbodig, je kan ook het ene veld meerdere keren gebruiken, toch?

[edit] en weer net te laat.

[ Voor 8% gewijzigd door Nick_S op 19-11-2004 16:03 ]

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Verwijderd

Topicstarter
De waarde zou anders zijn met een andere Identiteitstoename (incremental value) :)

De vraag blijft dus geldig ;)

  • André
  • Registratie: Maart 2002
  • Laatst online: 20-12 14:22

André

Analytics dude

Een record krijgt een uniek id: het autonummeringsveld. Dan ben je toch niet meer unieke id's nodig bij een record?

  • Dido
  • Registratie: Maart 2002
  • Laatst online: 12:52

Dido

heforshe

Verwijderd schreef op vrijdag 19 november 2004 @ 16:05:
De waarde zou anders zijn met een andere Identiteitstoename (incremental value) :)

De vraag blijft dus geldig ;)
Dan is je tweede veld dus x keer de waarde van je eerste veld: doodeenvoudig af te leiden gegevens dus. Waarom zou je die dan in je tabel willen hebben :?

Wat betekent mijn avatar?


Verwijderd

Topicstarter
André schreef op vrijdag 19 november 2004 @ 16:06:
Een record krijgt een uniek id: het autonummeringsveld. Dan ben je toch niet meer unieke id's nodig bij een record?
Het unieke ID is de primary key, ik vraag me dus af waarom ik niet een losstaande kolom in een tabel kan toevoegen die zijn eigen autonummering heeft, met een ander start nummer, een andere identificatietoename, etc. Denk ook aan een decimale verhoging per record, etc.
Dido schreef op vrijdag 19 november 2004 @ 16:08:
[...]

Dan is je tweede veld dus x keer de waarde van je eerste veld: doodeenvoudig af te leiden gegevens dus. Waarom zou je die dan in je tabel willen hebben :?
Omdat mijn systeem geen database is, maar een apart systeem met een begin waarde en een eind waarde, de vergelijking applicatie - database gaat in mijn geval niet op.

Dat is dus de reden voor de database, en dat heeft niks met mijn probleem te maken :o

Dus.. ik ga gewoon meerdere autonummeringsvelden toestaan in m'n applicatie :)

[ Voor 39% gewijzigd door Verwijderd op 19-11-2004 16:13 ]


  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 13:59

Nick_S

++?????++ Out of Cheese Error

Heb het net even getest in SQL Server, maar kan gewoon twee int identy velden aanmaken.

De ene met inc 1 (Dus 1, 2, 3, 4, etc) De ander met inc 3 (dus 1, 4, 7, 10). Dit zou dus ook een geldige reden voor dubbele identity velden kunnen zijn en is ook mogelijk. Of heb ik iets niet goed getest?

(Als dit weer een MS specifiek iets is, sorry voor deze post, maar heb even geen andere DBMS in de buurt)

[edit] Tijd voor weekend, zie net dat tijdens het aanmaken van de tweede identity de eerste weer op no is gezet.

[ Voor 13% gewijzigd door Nick_S op 19-11-2004 16:14 ]

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


  • Dido
  • Registratie: Maart 2002
  • Laatst online: 12:52

Dido

heforshe

Hoeveel moeite is het nou helemaal om dan die tweede waarde aan de hand van de eerste te berekenen?

/edit: ok, als het niet over databases blijkt te gaan is de vraag m.i. wat vaag gesteld, maar jouw vraag is dus wel beantwoord :) Weer een probleem minder :D

[ Voor 45% gewijzigd door Dido op 19-11-2004 16:15 ]

Wat betekent mijn avatar?


  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Nick_S schreef op vrijdag 19 november 2004 @ 16:12:
Heb het net even getest in SQL Server, maar kan gewoon twee int identy velden aanmaken.

De ene met inc 1 (Dus 1, 2, 3, 4, etc) De ander met inc 3 (dus 1, 4, 7, 10). Dit zou dus ook een geldige reden voor dubbele identity velden kunnen zijn en is ook mogelijk. Of heb ik iets niet goed getest?

(Als dit weer een MS specifiek iets is, sorry voor deze post, maar heb even geen andere DBMS in de buurt)
Weet je dat zeker, AFAIK kan dat niet met SQL Server.

Oops! Google Chrome could not find www.rijks%20museum.nl


  • SouLmaN
  • Registratie: Juli 2001
  • Laatst online: 15-12 19:44
Wees blij dat je autonummeringsvelden hebt... grmbl Oracle...

Zie het nut er ook niet echt van in

[ Voor 25% gewijzigd door SouLmaN op 19-11-2004 16:14 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Nick_S schreef op vrijdag 19 november 2004 @ 16:12:
Heb het net even getest in SQL Server, maar kan gewoon twee int identy velden aanmaken.

De ene met inc 1 (Dus 1, 2, 3, 4, etc) De ander met inc 3 (dus 1, 4, 7, 10). Dit zou dus ook een geldige reden voor dubbele identity velden kunnen zijn en is ook mogelijk. Of heb ik iets niet goed getest?

(Als dit weer een MS specifiek iets is, sorry voor deze post, maar heb even geen andere DBMS in de buurt)

[edit] Tijd voor weekend, zie net dat tijdens het aanmaken van de tweede identity de eerste weer op no is gezet.
Redundante data heet dat. Gegegevens die je makkelijk kunt mijden uit je database omdat ze te berekenen zijn, kun je er het beste ook gewoon uitlaten. Ik snap dan ook echt niet wat erop tegen is om gewoon een query als dit te doen:
SQL:
1
SELECT id, (id * 3 - 2) AS ander_veld FROM tabel

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Loesje
  • Registratie: Januari 2000
  • Laatst online: 02-07 17:57
Wees blij dat je autonummeringsvelden hebt... grmbl Oracle...
Zie het nut er ook niet echt van in
Het probleem van de TS is met Oracle juist heel makkelijk te verhelpen. Gewoon twee sequences aanmaken. Voordeel is dat je bv. een autonummeringsveld in meerdere tabellen kan gebruiken. (Kan daar eigenlijk ook geen nuttig voorbeeld voor geven)

En autonummering is toch zo gemaakt? Met een triggertje?

Leven is meervoud van lef


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Loesje schreef op vrijdag 19 november 2004 @ 16:25:
[...]
Het probleem van de TS is met Oracle juist heel makkelijk te verhelpen. Gewoon twee sequences aanmaken. Voordeel is dat je bv. een autonummeringsveld in meerdere tabellen kan gebruiken. (Kan daar eigenlijk ook geen nuttig voorbeeld voor geven)
Precies, het TS probleem is specifiek voor sqlserver, access, sybase, mysql... maar niet voor databases met sequences zoals DB2 en oracle
En autonummering is toch zo gemaakt? Met een triggertje?
Daar heb je niets aan, want je weet dan het laatst geinserte nummer niet, wat dus inhoudt dat de client het record niet meer kan lezen, want het weet de PK niet.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Daar heb je niets aan, want je weet dan het laatst geinserte nummer niet, wat dus inhoudt dat de client het record niet meer kan lezen, want het weet de PK niet.
De client weet de key ook niet met een autoinc field. Dat is dus geen nieuw probleem. Daarnaast kun je als je sequences hebt gewoon het laatst gebruikte sequence nummer uitlezen zonder je sequence op te hogen, of de waarde van de sequence naar de client halen en de client het record mét de waarde voor de PK laten invoegen.
Triggers zijn dan ook meestal flexibeler dan Autoinc velden, maar autoinc velden zijn een heel stuk makkelijker voor noobs.

Maar zonder sequences of (meerdere :) ) autoinc velden kun je vrij eenvoudig een eigen sequence tabel genereren. Wel moet je database dan constructies als SELECT FOR UPDATE aankunnen. Je wilt namelijk voorkomen dat meerdere gebruikers tegelijkertijd hetzelfde nummer toevoegen.
De basis is zoiets als dit

Tabeltje Keyvalues met een structuur als dit

Field Text (PK) Veldnaam waar je een Autoinc veld van wilt maken
Value Numeriek De huidige waarde van het veld
Inc Numeriek Het verschil tussen twee waarden
Max Numeriek De maximum waarde die het value field kan aannemen. Wordt value hoger, start dan opnieuw (value = value modulo max)

En een stuk code (in je insert trigger) die ongeveer zo werkt

Bepaal de waarde die je wilt inserten
Select value as valuepar, inc as Incpar, Max as Maxpar for update from keyvalues where Field="VELDNAAM"
Valuepar = (valuepar + incpar) modulo Max
Update keyvalues set value=valuepar where Field="VELDNAAM"

Voeg de waarde toe aan de toe te voegen data.
Set VELDNAAM=Valuepar

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op zaterdag 20 november 2004 @ 15:56:
[...]

De client weet de key ook niet met een autoinc field. Dat is dus geen nieuw probleem.
Jawel want DIE zijn meestal opvraagbaar middels SCOPE_IDENTITY(), @@IDENTITY en aanverwante zaken.
Triggers zijn dan ook meestal flexibeler dan Autoinc velden, maar autoinc velden zijn een heel stuk makkelijker voor noobs.
Wat een onzinnige opmerking, want triggers voor sequences zijn dermate zinloos dat je er niets aan hebt, plus moet je in triggers OF terugvallen op sequences (en dan heb je geen trigger nodig) of je gaat ranzige sql toepassen die bv de max value ophaalt en dan het volgende nummer daaruit berekend...

Geef me maar eens 1 reden waarom ik sequences niet direct in de insert zou gebruiken maar een trigger zou gebruiken.
Maar zonder sequences of (meerdere :) ) autoinc velden kun je vrij eenvoudig een eigen sequence tabel genereren. Wel moet je database dan constructies als SELECT FOR UPDATE aankunnen. Je wilt namelijk voorkomen dat meerdere gebruikers tegelijkertijd hetzelfde nummer toevoegen.
De basis is zoiets als dit

Tabeltje Keyvalues met een structuur als dit

Field Text (PK) Veldnaam waar je een Autoinc veld van wilt maken
Value Numeriek De huidige waarde van het veld
Inc Numeriek Het verschil tussen twee waarden
Max Numeriek De maximum waarde die het value field kan aannemen. Wordt value hoger, start dan opnieuw (value = value modulo max)

En een stuk code (in je insert trigger) die ongeveer zo werkt

Bepaal de waarde die je wilt inserten
Select value as valuepar, inc as Incpar, Max as Maxpar for update from keyvalues where Field="VELDNAAM"
Valuepar = (valuepar + incpar) modulo Max
Update keyvalues set value=valuepar where Field="VELDNAAM"

Voeg de waarde toe aan de toe te voegen data.
Set VELDNAAM=Valuepar
En toen waren er 2 threads die een query op die table deden....

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • avon
  • Registratie: November 2002
  • Laatst online: 27-06 12:38
Bij Access is het ook mogelijk om 2 unieke sleutels aan te maken, bijvoorbeeld met een
Replicatie ID en een Autonummering!.

Gratis webwinkel beginnen? Met Onetoshop.com kunt u direct beginnen!


Verwijderd

EfBe schreef op zaterdag 20 november 2004 @ 18:32:
Jawel want DIE zijn meestal opvraagbaar middels SCOPE_IDENTITY(), @@IDENTITY en aanverwante zaken.
Net zoals sequences dus. De autoinc waarde wordt op de server toegewezen. De client moet daarna extra werk doen om de laatste waarde terug te vinden. Hetzelde geldt voor sequences.
Wat een onzinnige opmerking, want triggers voor sequences zijn dermate zinloos dat je er niets aan hebt, plus moet je in triggers OF terugvallen op sequences (en dan heb je geen trigger nodig) of je gaat ranzige sql toepassen die bv de max value ophaalt en dan het volgende nummer daaruit berekend...
Kun jij in een autoinc veld niet lineair opvolgende nummers creeren, Kun jij je autoincveld beperken tot waarden tussen A en B, kun jij....
Een autoinc veld doet 1 ding goed maar met sequences en/of triggers ben je veel flexibeler. En "ranzige" SQL code is nog altijd beter dan géén oplossing. (zoals gezegd, bij gebrek aan sequences of autoinc velden)
Geef me maar eens 1 reden waarom ik sequences niet direct in de insert zou gebruiken maar een trigger zou gebruiken.
code:
1
2
IF ID=null  then
  ..

Wel eens gezien? Vaak wordt een insert op de client als volgt afgehandeld.
1) Haal een nieuwe unieke waarde van de server.
2) Voeg deze waarde toe aan de insert (Nu kun je dus altijd je record terugvinden wat ook de reden is dat het zo geprogrammeerd wordt)
3) Doe nu je daadwerkelijke update naar de database

Probleem: Als je nu een record toevoegt zonder waarde in het ID veld krijg je null waarden. Door te testen of er een waarde voor ID wordt meegegeven kun je in het geval dat er geen ID is alsnog een ID in de trigger toevoegen: Flexabiliteit!
En toen waren er 2 threads die een query op die table deden....
Twee woorden: FOR UPDATE (stond er zelfs al expliciet, leesbrillen zijn verkrijgbaar bij elke goede opticien)
Dat locked het record na de select totdat de update is uitgevoerd. Dus de tweede thread wacht totdat de eerste klaar is. Nog maar eens, niet de meest gewenste oplossing maar wel een oplossing die correct werkt. Zelfs bij héél veel gebruikers.

[ Voor 11% gewijzigd door Verwijderd op 21-11-2004 15:48 ]


  • Bartjuh
  • Registratie: Oktober 2001
  • Niet online

Bartjuh

Hej

Omdat je dan de tweede reeks rekenkundig kunt herleiden uit de eerste reeks, en dus volgens edgar codd een procesgegeven is, en die neem je niet mee in je database :)

Verwijderd

Ik kan me best wel een situatie voorstellen waarbij ik een dubbele autonumber zou willen hebben in een tabel. In Access zou je bijvoorbeeld een normale autonumber toe kunnen voegen om de volgorde van invoer bij te houden, en een replicatie ( = GUID ) autonummer om record over meerdere database uniek te houden. Kan handig zijn wanneer meerdere databases geconsolideerd moeten worden naar 1 database.

Maar echt vaak zal het niet voorkomen.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op zondag 21 november 2004 @ 13:21:
[...]
Net zoals sequences dus. De autoinc waarde wordt op de server toegewezen. De client moet daarna extra werk doen om de laatste waarde terug te vinden. Hetzelde geldt voor sequences.
ja, dat weet ik ook, maar jij zei:
De client weet de key ook niet met een autoinc field. Dat is dus geen nieuw probleem.
wat onzin is, want behalve bij triggers is het t.a.t. op te vragen. Jouw 'oplossing' mbt triggers echter niet. Daar kom ik zo op.
[...]
Kun jij in een autoinc veld niet lineair opvolgende nummers creeren, Kun jij je autoincveld beperken tot waarden tussen A en B, kun jij....
Jij kunt met je trigger ook geen lineaire opvolgende nummers creeeren. OF je moet ranzige code maken die omvalt bij de eerste de beste multi-user actie maar dan bespaar ik mezelf de moeite om hier nog verder tijd aan te besteden.

Een sequence, of je die nu met een trigger en een tabelletje maakt of van het OS krijgt, is nooit lineair te krijgen, je krijgt ALTIJD gaten. Dit komt omdat je een actie moet doen om het nummer dat je gaat inserten op te vragen en daarbij automatisch moet veiligstellen dat geen enkel andere thread dit nummer gebruikt. Als echter de insert faalt, kun je het nummer niet meer 'opnieuw' in roulatie brengen want dat resulteert onherroepelijk in dubbele waarden. ALs je dat niet inziet, doe maar eens een testje.

Iedere sequence kan overigens een range aan, dus ik zie het probleem niet echt.
Een autoinc veld doet 1 ding goed maar met sequences en/of triggers ben je veel flexibeler. En "ranzige" SQL code is nog altijd beter dan géén oplossing. (zoals gezegd, bij gebrek aan sequences of autoinc velden)
Jij veegt nu triggers en sequences op een hoop maar dat is dus niet wat jij beweerde. Sequences en identity columns zijn een groep, de trigger oplossing is een andere.

En 'ranzige' sql code is GEEN oplossing, want deze werkt nl. niet. Ook ken ik GEEN database die EN geen sequences EN geen identity ondersteunt.
[...]
code:
1
2
IF ID=null  then
  ..

Wel eens gezien?
Wat denk je zelf? Helaas wel eens gezien ja.
Vaak wordt een insert op de client als volgt afgehandeld.
1) Haal een nieuwe unieke waarde van de server.
2) Voeg deze waarde toe aan de insert (Nu kun je dus altijd je record terugvinden wat ook de reden is dat het zo geprogrammeerd wordt)
3) Doe nu je daadwerkelijke update naar de database

Probleem: Als je nu een record toevoegt zonder waarde in het ID veld krijg je null waarden. Door te testen of er een waarde voor ID wordt meegegeven kun je in het geval dat er geen ID is alsnog een ID in de trigger toevoegen: Flexabiliteit!
Je snapt er werkelijk niets van he? Je hebt 2 situaties: 1) databases met identity columns en 2) databases met sequences.

Situatie 1) is simpel: je insert je record en vermeldt geen waarde voor de identity column. De identity functionaliteit van de database geeft de identity column automatisch een nieuwe waarde, welke is uit te vragen door de daarvoor bestemde systeem functie aan te roepen of variable uit te lezen en die waarde in een output parameter te stoppen.
Situatie 2) is nog simpeler: eerst een scalar query aanroepen om de nieuwe waarde van de sequence te krijgen, dan de insert doen met de nieuwe sequence waarde als waarde voor de sequenced column. (kun je ook doen zoals oplossing 1 overigens)

Waar heb ik triggers nodig? Ik zie de noodzaak niet. Sterker nog: dit werkt _ALTIJD_, zonder enige vrees voor multi-user problemen of ranzige locks op een table omdat een sequence toch vooral met de hand moest worden gemaakt.
[...]
Twee woorden: FOR UPDATE (stond er zelfs al expliciet, leesbrillen zijn verkrijgbaar bij elke goede opticien)
So?
Dat locked het record na de select totdat de update is uitgevoerd. Dus de tweede thread wacht totdat de eerste klaar is. Nog maar eens, niet de meest gewenste oplossing maar wel een oplossing die correct werkt. Zelfs bij héél veel gebruikers.
Nou wat werkt deze perfect.... de lock wordt vrijgegeven wanneer de transaction wordt gecommit... lijkt me een mooie voor de DBA om de deadlocks uit het systeem te halen wanneer er ineens wat meer gebruikers op het systeem komen. En ga me nou niet vertellen dat deze 'oplossing' geen deadlocks creeert...

Maar goed, ik heb wel weer genoeg gezeik gezien hier in deze thread. Als mensen zelfgeschreven prut in triggers gaan lopen aanprijzen om constructs die in elke zelfrespecterende database zijn ingebakken te omzeilen dan houdt het hard op.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • SuperRembo
  • Registratie: Juni 2000
  • Laatst online: 20-08 14:36
P_de_B schreef op vrijdag 19 november 2004 @ 16:13:
[...]


Weet je dat zeker, AFAIK kan dat niet met SQL Server.
Het kan niet, alleen lijkt het misschien te kunnen als je met de Sql Server Manager zo'n tabel probeert te maken. Sql Server Manager zorgt er voor dat er maar 1 identity kolom is, als je een tweede instelt zet ie de eerste uit (zonder waarschuwing).

| Toen / Nu


  • PromWarMachine
  • Registratie: Oktober 2001
  • Laatst online: 20-12 13:31

PromWarMachine

Forsaken Archer

Simpel: Redundantie.

Als je 2 velden automatisch wilt laten nummeren. Bijvoorbeeld de ene steeds met 1 verhogen en de andere steeds met 2. Dan is de tweede altijd 2x zo hoog als de eerste. Dat maakt het redundant. Je kunt immers de tweede altijd berekenen, aan de hand van de eerste.

Ook als het ingewikkelder wordt, is het altijd te berekenen. Dingen die te berekenen zijn, sla je niet op in een database. :)

[ Voor 1% gewijzigd door PromWarMachine op 21-11-2004 18:19 . Reden: typo ]

Dividend for Starters


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

EfBe schreef op zaterdag 20 november 2004 @ 18:32:
Wat een onzinnige opmerking, want triggers voor sequences zijn dermate zinloos dat je er niets aan hebt, plus moet je in triggers OF terugvallen op sequences (en dan heb je geen trigger nodig) of je gaat ranzige sql toepassen die bv de max value ophaalt en dan het volgende nummer daaruit berekend...

Geef me maar eens 1 reden waarom ik sequences niet direct in de insert zou gebruiken maar een trigger zou gebruiken.
Als je wilt forceren dat er nooit een andere waarde dan door de sequence gegenereerd wordt ingevoerd door de database.

Een ander potentieel nut: Ik weet trouwens niet of je bij bijv Oracle ook een "default value" op kan geven voor een sequence-based kolom, waardoor standaard een sequence waarde wordt opgenomen als je het veld leeg laat bij je insert.
Als dat niet dmv een default waarde kan, dan is het niet per se nutteloos om die default dan maar met een trigger uit te voeren. 't Scheelt iig wat werk in je queries (wat je kan vergeten) om dan maar steeds een select op je sequence uit te voeren bij de insert.

  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 08:17

JaQ

ACM schreef op zondag 21 november 2004 @ 18:49:
[...]

Als je wilt forceren dat er nooit een andere waarde dan door de sequence gegenereerd wordt ingevoerd door de database.

Een ander potentieel nut: Ik weet trouwens niet of je bij bijv Oracle ook een "default value" op kan geven voor een sequence-based kolom, waardoor standaard een sequence waarde wordt opgenomen als je het veld leeg laat bij je insert.
Als dat niet dmv een default waarde kan, dan is het niet per se nutteloos om die default dan maar met een trigger uit te voeren. 't Scheelt iig wat werk in je queries (wat je kan vergeten) om dan maar steeds een select op je sequence uit te voeren bij de insert.
2 x punt. In ieder geval is het in oudere versies van Oracle niet mogelijk om een sequence als default aan te wijzen (weet niet 100% zeker of het ondertussen wel kan).

Efbe --> Gaaf dat je denkt dat je alles weet, maar het argument dat je het laatste geinserte ID niet kent bij een trigger is volledig ongeldig. Dat weet je ook niet als je de sequence in je query aanroept. Die sequence waarde is niet sessie afhankelijk, dus bij een multi user actie is je waarde die je gaat uitvragen ook potentieel onjuist. Om die echt zeker te weten zou je eerst de sequence in een (bind) variabele moeten zetten en dan moeten gebruiken in je insert statement (dus niet flamen zonder dat je je eigen shit op orde hebt)

Om terug te komen op het probleem van de TS. Er is geen enkele reden om een autonummer twee maal op te nemen in 1 tabel, want het is altijd afleidbaar.

Egoist: A person of low taste, more interested in themselves than in me


Verwijderd

Koop nu maar die leesbril, je begrijpt blijkbaar niet wat er staat.
niet lineair oplopende nummers, dus nummers die bv zo gecreeert worden 1,2,3,5,8,13,....

Is wat anders dan
Een sequence, of je die nu met een trigger en een tabelletje maakt of van het OS krijgt, is nooit lineair te krijgen, je krijgt ALTIJD gaten.
Maar dat lezen. Blijft lastig.
En 'ranzige' sql code is GEEN oplossing, want deze werkt nl. niet. Ook ken ik GEEN database die EN geen sequences EN geen identity ondersteunt.
Dat is dan een nieuwe definitie van ranzige code. De meeste mensen noemen dat gewoon niet werkende code. Ranzige code is code die wel werkt maar niet efficient is en/of volkomen onleesbaar. Je laat het erin staan omdat het werkt en je niets beters weet maar het is en blijft troep.
En dat je geen databases kent die en geen sequences kent en geen identity kolommen ondersteunen kan kloppen, echter dat wil niet zeggen dat het nooit efficient is om zelf sequences via triggers te kunnen genereren. Ik heb nooit beweerd dat het de beste keus is enkel
zonder sequences of (meerdere ) autoinc velden
In die gevallen kan het handig zijn om zelf iets in elkaar te draaien. Niet optimaal (Sequences hebben het voordeel dat ze bv buiten transacties vallen) maar beter dan niets.
Situatie 2) is nog simpeler: eerst een scalar query aanroepen om de nieuwe waarde van de sequence te krijgen, dan de insert doen met de nieuwe sequence waarde als waarde voor de sequenced column. (kun je ook doen zoals oplossing 1 overigens)
Dus
1) Haal een nieuwe unieke waarde van de server.
2) Voeg deze waarde toe aan de insert (Nu kun je dus altijd je record terugvinden wat ook de reden is dat het zo geprogrammeerd wordt)
3) Doe nu je daadwerkelijke update naar de database
Komt het je bekend voor?

En waarom de if? Echt geen idee? Wel eens gehoord van Legacy Code? Of van standaard import tools? Misschien wel eens een database gezien die sequences niet als default accepteert?
Nou wat werkt deze perfect.... de lock wordt vrijgegeven wanneer de transaction wordt gecommit... lijkt me een mooie voor de DBA om de deadlocks uit het systeem te halen wanneer er ineens wat meer gebruikers op het systeem komen. En ga me nou niet vertellen dat deze 'oplossing' geen deadlocks creeert...
Altijd leuk eerst volkomen erover heen lezen en dan het nog niet willen begrijpen.
Deze code is niet perfect, dat klopt. Helaas is het niet zo dat je makkelijk code buiten transacties kan houden (zoals sequences wél buiten de transacties blijven)
Echter vaak wordt de drie stappen manier die hierboven 3 keer staat gebruikt. Dan is het vrij eenvoudig om stap 1 in een aparte transactie te stoppen. Daarnaast is deze methode enkel handig bij gebrek aan
sequences of (meerdere ) autoinc velden
Ja, het is niet perfect, maar dit soort methodes werkt vrij aardig om velden te vullen met standaard waarden als je db er niet voor kan zorgen. En mits met beleid toegepast ondersteund deze methode een hele hoop gebruikers.

Tot slot, lang niet iedereen gebruikt (helaas) transacties. Je moet voor de grap eens uitzoeken in welke versie van MySQL transacties werden toegevoegd. Zonder transacties wordt de lock wél gelijk vrijgegeven. Persoonlijk niet iets waar ik erg blij mee bent maar wel waar.
Maar goed, ik heb wel weer genoeg gezeik gezien hier in deze thread. Als mensen zelfgeschreven prut in triggers gaan lopen aanprijzen om constructs die in elke zelfrespecterende database zijn ingebakken te omzeilen dan houdt het hard op.
Ach, als je database het niet ondersteund is die zelfgeschreven prut toch wel érg handig. Maar misschien kan ik je wel een leescursus opsturen?

[ Voor 8% gewijzigd door Verwijderd op 22-11-2004 01:52 ]


  • dvvelzen
  • Registratie: Februari 2002
  • Laatst online: 07-08 19:20
Ik wil niet vervelend zijn, maar iig in ASE (sybase) weet je je waarden wel bij een trigger.....

inserted en deleted zijn de tabellen met de waarden die gerelateerd zijn aan de toegevoegde/verwijderde gegevens van de tabel waar je trigger aan hangt.

Hier kan je dus ook je ID's uit halen .... :)

gr,
Dennis

  • dvvelzen
  • Registratie: Februari 2002
  • Laatst online: 07-08 19:20
Verwijderd schreef op maandag 22 november 2004 @ 01:26:
En dat je geen databases kent die en geen sequences kent en geen identity kolommen ondersteunen kan kloppen, echter dat wil niet zeggen dat het nooit efficient is om zelf sequences via triggers te kunnen genereren....
Ik wil niet lastig zijn, maar een trigger vooral bij dikke inserts kan leiden tot deferred updates en dat is iets wat je toch niet echt wil lijkt me....
Verwijderd schreef op maandag 22 november 2004 @ 01:26:
Ach, als je database het niet ondersteund is die zelfgeschreven prut toch wel érg handig. Maar misschien kan ik je wel een leescursus opsturen?
Persoonlijk ben ik van mening dat je beter je opslag strategie beter iets kan tweaken dan je functionaliteit buiten de db te halen. Mits dit tijdens het opslag proces gebeurt. Ik zou er altijd voor zorgen dan je met 1 db connectie een transactie volledig kan afhandelen dus niet eerst een nummer ophalen en dan verder gaan enzo....

maar dat is mijn mening...


gr,
Dennis

[ Voor 39% gewijzigd door dvvelzen op 22-11-2004 08:21 ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
DrFrankenstoner schreef op zondag 21 november 2004 @ 20:17:
Efbe --> Gaaf dat je denkt dat je alles weet, maar het argument dat je het laatste geinserte ID niet kent bij een trigger is volledig ongeldig. Dat weet je ook niet als je de sequence in je query aanroept. Die sequence waarde is niet sessie afhankelijk, dus bij een multi user actie is je waarde die je gaat uitvragen ook potentieel onjuist. Om die echt zeker te weten zou je eerst de sequence in een (bind) variabele moeten zetten en dan moeten gebruiken in je insert statement (dus niet flamen zonder dat je je eigen shit op orde hebt)
Erm... bij een sequence kan ik altijd achterhalen wat de waarde was, bij een trigger NOOIT. Veel sequence varianten kennen een current value achtig iets die geldig is voor de huidige connection. Hoezo ik kan deze niet opvragen? (Firebird dacht ik niet, het is maandag, ik moet dat even opzoeken) En wanneer dat niet het geval is, dan vraag je de sequence EERST op en gebruik je dan een insert query. Bij een trigger weet je het nummer nooit, bij een sequence ALTIJD.

Ik flame verder niet, mij wordt verweten dat ik leesbrillen op moet en ik moet dingen verdedigen die normaal zijn tegen mensen die triggers propageren voor autosequences met ranzige sequence tables en daarbij beweren dat triggers WEL lineaire sequences opleveren. Mja, einde oefening.

Wie heeft zn shit trouwens niet op orde? Heb jij dit soort code geschreven voor 6 verschillende databases? Wat denk je dat ik het niet weet?
Om terug te komen op het probleem van de TS. Er is geen enkele reden om een autonummer twee maal op te nemen in 1 tabel, want het is altijd afleidbaar.
Nee ook dit is niet waar. Voorbeeld: 1 autonumber voor een unieke key en 1 autonumber dat oploopt per dag (bijvoorbeeld).
dvvelzen schreef op maandag 22 november 2004 @ 08:10:
Ik wil niet vervelend zijn, maar iig in ASE (sybase) weet je je waarden wel bij een trigger.....

inserted en deleted zijn de tabellen met de waarden die gerelateerd zijn aan de toegevoegde/verwijderde gegevens van de tabel waar je trigger aan hangt.

Hier kan je dus ook je ID's uit halen .... :)
Ja duh, maar welke waarde jij insert als een update in het laatst geinserte record, weet jij niet, want de trigger draait in dezelfde transaction als het insert statement maar jij kunt geen waardes teruggeven aan het insertstatement of de context waarin het insertstatement draait, waardoor je dat nummer niet terug kunt geven aan de caller. DAT is het probleem.

Als dat niet erg is, tja, dan heb je geen probleem, maar veelal is het wel degelijk nuttig te weten wat de key is van het record dat je net hebt geinsert. Bv om gerelateerde records te saven die een FK hebben naar het laatst gesavede record, ik noem maar iets triviaals.

[ Voor 23% gewijzigd door EfBe op 22-11-2004 09:38 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op maandag 22 november 2004 @ 01:26:
[snip flames]

En dat je geen databases kent die en geen sequences kent en geen identity kolommen ondersteunen kan kloppen, echter dat wil niet zeggen dat het nooit efficient is om zelf sequences via triggers te kunnen genereren. Ik heb nooit beweerd dat het de beste keus is enkel
Jij zei dat die trigger methode handig was wanneer er geen identity of sequences waren, en dat leek me een loze opmerking want die databases zijn er niet.
En waarom de if? Echt geen idee? Wel eens gehoord van Legacy Code? Of van standaard import tools? Misschien wel eens een database gezien die sequences niet als default accepteert?
wat houdt 'sequences niet als default accepteert' in? Dat je geen values in een identity column kan inserten?
Altijd leuk eerst volkomen erover heen lezen en dan het nog niet willen begrijpen.
Deze code is niet perfect, dat klopt. Helaas is het niet zo dat je makkelijk code buiten transacties kan houden (zoals sequences wél buiten de transacties blijven)
Echter vaak wordt de drie stappen manier die hierboven 3 keer staat gebruikt. Dan is het vrij eenvoudig om stap 1 in een aparte transactie te stoppen. Daarnaast is deze methode enkel handig bij gebrek aan
[...]
Ja, het is niet perfect, maar dit soort methodes werkt vrij aardig om velden te vullen met standaard waarden als je db er niet voor kan zorgen. En mits met beleid toegepast ondersteund deze methode een hele hoop gebruikers.
Hoe kan een trigger buiten een transactie draaien, als deze altijd in de transaction van het insert statement draait?
Tot slot, lang niet iedereen gebruikt (helaas) transacties. Je moet voor de grap eens uitzoeken in welke versie van MySQL transacties werden toegevoegd. Zonder transacties wordt de lock wél gelijk vrijgegeven. Persoonlijk niet iets waar ik erg blij mee bent maar wel waar.
InnoDB kent dat al een tijdje, maar MySQL kent ook identity columns (auto_increment) dus waarom ranzig doen? Trouwens ondersteunt MySql niet pas sinds v5 triggers?
Ach, als je database het niet ondersteund is die zelfgeschreven prut toch wel érg handig. Maar misschien kan ik je wel een leescursus opsturen?
Misschien moet jij je praatjes wat matigen ipv mensen af te lopen zeiken dat ze niet lezen.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • justmental
  • Registratie: April 2000
  • Niet online

justmental

my heart, the beat

EfBe schreef op maandag 22 november 2004 @ 09:34:
Ja duh, maar welke waarde jij insert als een update in het laatst geinserte record, weet jij niet, want de trigger draait in dezelfde transaction als het insert statement maar jij kunt geen waardes teruggeven aan het insertstatement of de context waarin het insertstatement draait, waardoor je dat nummer niet terug kunt geven aan de caller. DAT is het probleem.
In Oracle kan dit wel, maar deze is daarin waarschijnlijk een uitzondering.
Bij het insert statement heb je een 'returning' clausule waarin je de geinserte sequencewaarde terug kunt geven.

Who is John Galt?


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

EfBe schreef op maandag 22 november 2004 @ 09:34:
Erm... bij een sequence kan ik altijd achterhalen wat de waarde was, bij een trigger NOOIT
Ik had het over een trigger om een sequence te gebruiken en kan je garanderen dat je daarmee sowieso de sequence-waarde in Oracle kan gebruiken. Maar waarom kan een trigger niet de waarde achterhalen :?
Als je de trigger gebruikt om die "sequence tabel" te gebruiken, MOET je de actuele waarde uit die tabel halen, een increment op die waarde (en dat in een (nested) transaction natuurlijk) en die oude waarde gebruiken voor het nieuwe record.
Veel sequence varianten kennen een current value achtig iets die geldig is voor de huidige connection. Hoezo ik kan deze niet opvragen? (Firebird dacht ik niet, het is maandag, ik moet dat even opzoeken) En wanneer dat niet het geval is, dan vraag je de sequence EERST op en gebruik je dan een insert query. Bij een trigger weet je het nummer nooit, bij een sequence ALTIJD.
Een trigger kan toch vrijwel precies hetzelfde als een losse query??
Dit kan toch gewoon in een trigger:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
-- PSEUDO PL/SQL
CREATE TRIGGER insert_trigger BEFORE INSERT ON data_tabel
   FOR EACH ROW
   temp_val INTEGER;
BEGIN -- start van transactie
   SELECT current_value INTO temp_val 
           FROM sequence_tabel WHERE sequence_id = 'data_tabel';
   UPDATE sequence_tabel SET current_value = current_value + 1 
           WHERE sequence_id = 'data_tabel';

   NEW.data_id := temp_val;
END


Leg mij dan eens uit waarom dit niet "net zo goed" als sequences kan werken? (tuurlijk insert into tabelnaam values (nextval('data_tabel_sequence'), ...) is handiger en vast ook significant sneller).
Wie heeft zn shit trouwens niet op orde? Heb jij dit soort code geschreven voor 6 verschillende databases? Wat denk je dat ik het niet weet?
Sequences zijn ook niet in 6 verschillende databases hetzelfde :P
Zelfs PostgreSQL dat vaak gemodelleerd wordt naar Oracle verschilt sterk op een aantal punten van Oracle met sequences. En in firebird heet het dan weer Generators, etc.
Ja duh, maar welke waarde jij insert als een update in het laatst geinserte record, weet jij niet, want de trigger draait in dezelfde transaction als het insert statement maar jij kunt geen waardes teruggeven aan het insertstatement of de context waarin het insertstatement draait, waardoor je dat nummer niet terug kunt geven aan de caller. DAT is het probleem.

Als dat niet erg is, tja, dan heb je geen probleem, maar veelal is het wel degelijk nuttig te weten wat de key is van het record dat je net hebt geinsert. Bv om gerelateerde records te saven die een FK hebben naar het laatst gesavede record, ik noem maar iets triviaals.
Dat is inderdaad een valide punt. Maar maakt e.e.a. niet ineens ranzig :P
Dit zou je dan weer op moeten lossen door meer sql-code in je client te stoppen (die binnen een transactie een select op de sequence_tabel's huidige waarde doet) of door het in een stored procedure te stoppen.

Met de strekking van je verhaal ben ik het overigens wel eens "gebruik de mogelijkheden van je db, niet een custom built oplossing, indien mogelijk. Dus gebruik sequences of autonummering en geen eigen oplossing indien dat doet wat je nodig hebt" :)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

EfBe schreef op maandag 22 november 2004 @ 09:44:
wat houdt 'sequences niet als default accepteert' in? Dat je geen values in een identity column kan inserten?
In PostgreSQL kan dit:
SQL:
1
2
3
4
5
CREATE TABLE ...
idkolom INTEGER DEFAULT nextval('sequence_naam')
-- wat min of meer synoniem is aan:
id2kolom SERIAL
...

Toen ik Oracle 8.x gebruikte kon ik niet vinden hoe ik iets vergelijkbaars kon doen en ook de code-voorbeelden waar ik toen mee werkte om automatisch velden een sequence-waarde te geven gebruikten triggers. Misschien dat bovenstaande nu (of zelfs toen) wel in Oracle kan, maar dat is iig wat ik ermee bedoelde.
InnoDB kent dat al een tijdje, maar MySQL kent ook identity columns (auto_increment) dus waarom ranzig doen? Trouwens ondersteunt MySql niet pas sinds v5 triggers?
Ik geloof niet dat je al van 'sinds v5' kan spreken :P

[ Voor 4% gewijzigd door ACM op 22-11-2004 10:33 ]


  • JaQ
  • Registratie: Juni 2001
  • Laatst online: 08:17

JaQ

EfBe schreef op maandag 22 november 2004 @ 09:34:
[...]
Erm... bij een sequence kan ik altijd achterhalen wat de waarde was, bij een trigger NOOIT. Veel sequence varianten kennen een current value achtig iets die geldig is voor de huidige connection. Hoezo ik kan deze niet opvragen? (Firebird dacht ik niet, het is maandag, ik moet dat even opzoeken) En wanneer dat niet het geval is, dan vraag je de sequence EERST op en gebruik je dan een insert query. Bij een trigger weet je het nummer nooit, bij een sequence ALTIJD.

Ik flame verder niet, mij wordt verweten dat ik leesbrillen op moet en ik moet dingen verdedigen die normaal zijn tegen mensen die triggers propageren voor autosequences met ranzige sequence tables en daarbij beweren dat triggers WEL lineaire sequences opleveren. Mja, einde oefening.

Wie heeft zn shit trouwens niet op orde? Heb jij dit soort code geschreven voor 6 verschillende databases? Wat denk je dat ik het niet weet?
De current value die je opvraagt van je sequence is niet per definitie de juiste, dat probeerde ik je duidelijk te maken. Leuk trouwens dat je de oplossing die ik als enige zekerheid op de vlak (ophalen en in een variable zetten) herhaald. Discussieren terwijl we het eens zijn dus ;)

Ik wil je zeker niet persoonlijk aanvallen, laat ik daar even heel duidelijk in zijn. Wordt alleen de laatste tijd een beetje moe van de "ik-weet-alles-beter-dan-jij" sfeer die zowel hier als in NOS begint te hangen. (I know, i know.. if you don't like it, get the f*ck out of there).

Je hebt helemaal gelijk dat een trigger geen lineaire sequence op kan leveren. Een gat in de range is altijd mogelijk. (Tenzij je zelf een stuk code gaat schrijven wat die gaten opzoekt en deze opnieuw uitdeelt, maar ik zie niet in waarom je dat zou willen).

Anyway, de hoeveelheid verschillende databases waar ik mee heb gewerkt gaat verder dan 6 (en MySql kan ik nog steeds geen database noemen dus tel ik ook zeker niet mee). Ben ik nou stoer, of is het helemaal niet relevant voor hoeveel databases ik (of jij) dit soort code hebt geschreven.

Op je laatste vraag: Ik denk dat je redelijk goed weet waar je over praat, maar soms een beetje ongenuanceerd uit de hoek komt. Erg vervelend voor je als je als ontwikkelaar werkt, want dat gaat je vanzelf een keer in je zak bijten. Soms ben je niet de meest briljante ontwikkelaar in een team en erger nog: soms heb je een (technisch) projectleider die dat soort gedrag gewoon niet pikt. Maar goed, dit is een forum en niet IRL, misschien ben je IRL wel wat kalmer en genuanceerder. (nofi uiteraard, meer een losse gedachte)
dvvelzen schreef op maandag 22 november 2004 @ 08:14:
[...]

Ik wil niet lastig zijn, maar een trigger vooral bij dikke inserts kan leiden tot deferred updates en dat is iets wat je toch niet echt wil lijkt me....
Soms wel. Stel dat jij voor alle acties die gebeuren in de database een journaal wilt bijhouden. Dus voor iedere update, wil jij dat de originele waarde in een history tabel (een journaal dus) wordt weggeschreven?

Ook kan een insert (of update) een bepaald stuk business logic triggeren. Die event trigger kan je natuurlijk in een applicatie hangen, maar waarom niet in de database? (Daarmee dreig ik wel weer de discussie over logica in de database of niet aan te wakkeren)

Deferred updates zijn dus niet per definitie slecht. Zolang ze maar goed gedocumenteerd zijn voor de DBA-ers ;)

Egoist: A person of low taste, more interested in themselves than in me


  • EfBe
  • Registratie: Januari 2000
  • Niet online
justmental schreef op maandag 22 november 2004 @ 09:49:
[...]
In Oracle kan dit wel, maar deze is daarin waarschijnlijk een uitzondering.
Bij het insert statement heb je een 'returning' clausule waarin je de geinserte sequencewaarde terug kunt geven.
Ah, bedankt voor de tip. Inderdaad voorzover ik weet is dit uniek, of DB2 moet er ook een clause voor hebben, wat me niet zou verbazen.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
ACM schreef op maandag 22 november 2004 @ 10:27:
Ik had het over een trigger om een sequence te gebruiken en kan je garanderen dat je daarmee sowieso de sequence-waarde in Oracle kan gebruiken. Maar waarom kan een trigger niet de waarde achterhalen :?
Nee, ik bedoelde: de waarde die geinsert wordt TERUGGEVEN. Een trigger is in theorie autonoom: onderdeel van het insert/update/delete statement maar kan geen waarden teruggeven aan de context waar het insert/update/delete statement wordt gecalled.
Als je de trigger gebruikt om die "sequence tabel" te gebruiken, MOET je de actuele waarde uit die tabel halen, een increment op die waarde (en dat in een (nested) transaction natuurlijk) en die oude waarde gebruiken voor het nieuwe record.
Ja, maar dat was het probleem niet ;). (overigens is een trigger-achtige constructie beter te doen in een proc die middels een serialized transaction de handel afhandelt en de nieuwe waarde teruggeeft. Die is dan gewoon te gebruiken door de client en altijd uniek (maar niet echt schaalbaar)
[...]
Een trigger kan toch vrijwel precies hetzelfde als een losse query??
Dit kan toch gewoon in een trigger:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
-- PSEUDO PL/SQL
CREATE TRIGGER insert_trigger BEFORE INSERT ON data_tabel
   FOR EACH ROW
   temp_val INTEGER;
BEGIN -- start van transactie
   SELECT current_value INTO temp_val 
           FROM sequence_tabel WHERE sequence_id = 'data_tabel';
   UPDATE sequence_tabel SET current_value = current_value + 1 
           WHERE sequence_id = 'data_tabel';

   NEW.data_id := temp_val;
END


Leg mij dan eens uit waarom dit niet "net zo goed" als sequences kan werken? (tuurlijk insert into tabelnaam values (nextval('data_tabel_sequence'), ...) is handiger en vast ook significant sneller).
omdat meerdere threads dezelfde waarde kunnen ophalen en een context switch kan plaatsvinden tussen select en update. Les 1 van concurrent programming. :). Je kunt met locking wel allerlei dingen proberen af te vangen, en dan lukt het 'wel', maar door die locking kun je in de problemen komen doordat er deadlocks kunnen ontstaan.
Sequences zijn ook niet in 6 verschillende databases hetzelfde :P
Zelfs PostgreSQL dat vaak gemodelleerd wordt naar Oracle verschilt sterk op een aantal punten van Oracle met sequences. En in firebird heet het dan weer Generators, etc.
Ja dat klopt, het principe is echter hetzelfde: een door het systeem gegenereerde nieuwe waarde in een sequentiele reeks. Een Identity column is ook gewoon een sequence alleen heb je de vrijheid niet om die sequence ergens anders ook nog te gebruiken. DB2 heeft beide, en je ziet aan discussies omtrent wanneer wat te gebruiken (Identity of sequences) waar de nadelen van beide zitten. Over het algemeen is identity makkelijker maar minder flexibel (en dat is met bijna alles zo ;))
Dat is inderdaad een valide punt. Maar maakt e.e.a. niet ineens ranzig :P
Dit zou je dan weer op moeten lossen door meer sql-code in je client te stoppen (die binnen een transactie een select op de sequence_tabel's huidige waarde doet) of door het in een stored procedure te stoppen.
Klopt. Je ontkomt in je custom oplossing niet aan een low-level locks. Echter bv op sqlserver kan ik altijd lezen van een gelockte row door een hint op te geven. Ja, dat is ranzig, maar sommige programmeurs gebruiken het om deadlocks te voorkomen (ook ranzig, maar dat terzijde). De door het RDBMS aangereikte mechanismen hebben deze nadelen niet.
DrFrankenstoner schreef op maandag 22 november 2004 @ 13:04:
De current value die je opvraagt van je sequence is niet per definitie de juiste, dat probeerde ik je duidelijk te maken.
dit zul je me even moeten uitleggen. Ik begrijp dat bij verschillende nextval calls de vorige values niet meer bekend zijn (goh ;)) maar als ik insert en daarna een scalar query, bv SELECT mysequence.CURRVAL FROM DUAL; doe (oracle) waarom zou dat niet de juiste waarde opleveren die is gebruikt in de insert?
Ik wil je zeker niet persoonlijk aanvallen, laat ik daar even heel duidelijk in zijn. Wordt alleen de laatste tijd een beetje moe van de "ik-weet-alles-beter-dan-jij" sfeer die zowel hier als in NOS begint te hangen. (I know, i know.. if you don't like it, get the f*ck out of there).
Ach, valt wel mee toch? (hier that is).
Anyway, de hoeveelheid verschillende databases waar ik mee heb gewerkt gaat verder dan 6 (en MySql kan ik nog steeds geen database noemen dus tel ik ook zeker niet mee). Ben ik nou stoer, of is het helemaal niet relevant voor hoeveel databases ik (of jij) dit soort code hebt geschreven.
Mijn lijst gaat ook verder dan 6, maar ik wilde aangeven dat ik wel weet waarover ik praat mbt dit onderwerp :). Inderdaad een zwaktebod, toegegeven.
Op je laatste vraag: Ik denk dat je redelijk goed weet waar je over praat, maar soms een beetje ongenuanceerd uit de hoek komt. Erg vervelend voor je als je als ontwikkelaar werkt, want dat gaat je vanzelf een keer in je zak bijten. Soms ben je niet de meest briljante ontwikkelaar in een team en erger nog: soms heb je een (technisch) projectleider die dat soort gedrag gewoon niet pikt. Maar goed, dit is een forum en niet IRL, misschien ben je IRL wel wat kalmer en genuanceerder. (nofi uiteraard, meer een losse gedachte)
Mja, meestal probeer ik wel genuanceerd te zijn, maar wanneer ik meteen leesbrillen moet gaan kopen e.d. dan houdt het hard op.
Soms wel. Stel dat jij voor alle acties die gebeuren in de database een journaal wilt bijhouden. Dus voor iedere update, wil jij dat de originele waarde in een history tabel (een journaal dus) wordt weggeschreven?
Oh maar laat ik even rechtzetten dat ik niet tegen triggers ben, ik ben alleen tegen triggers voor het creeeren van autonumbering. Dat is iets heel anders.
Deferred updates zijn dus niet per definitie slecht. Zolang ze maar goed gedocumenteerd zijn voor de DBA-ers ;)
Laat ik me daar niet verder over uitlaten ;)

[ Voor 28% gewijzigd door EfBe op 22-11-2004 13:33 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
ACM schreef op maandag 22 november 2004 @ 10:32:
In PostgreSQL kan dit:
SQL:
1
2
3
4
5
CREATE TABLE ...
idkolom INTEGER DEFAULT nextval('sequence_naam')
-- wat min of meer synoniem is aan:
id2kolom SERIAL
...

Toen ik Oracle 8.x gebruikte kon ik niet vinden hoe ik iets vergelijkbaars kon doen en ook de code-voorbeelden waar ik toen mee werkte om automatisch velden een sequence-waarde te geven gebruikten triggers. Misschien dat bovenstaande nu (of zelfs toen) wel in Oracle kan, maar dat is iig wat ik ermee bedoelde.
Zei jan klaassen dat niet?

Dat terzijde, ik snap nu wat je bedoelt. In Oracle kun je natuurlijk een default constraint aanmaken die een functie aanroept, maar ook daar heb je als nadeel dat je dan de waarde die is geinsert niet weet. Veelal heb je die nodig om FK fields te vullen of om weer te refereren naar dit record. Tuurlijk, wanneer je alleen een synthetic key nodig hebt en je het verder worst zal zijn (logging e.d. bv) dan boeit het niet zo, echter de meerderheid van de data is gerelateerd opgeslagen en dan helpt het wel degelijk dat je die values terug kunt lezen: anders ligt data opgeslagen met een key maar die weet je niet. Nuttig! :)


[...]

Ik geloof niet dat je al van 'sinds v5' kan spreken :P[/quote]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

EfBe schreef op maandag 22 november 2004 @ 13:22:
Nee, ik bedoelde: de waarde die geinsert wordt TERUGGEVEN.
Dat was het stukje dat ik bij jouw uitleg nog niet helemaal had begrepen. Maar je hebt inderdaad gelijk op dat punt. Zodra je met locking moet werken om dat soort dingen te regelen begint het inderdaad richting ranzige oplossingen te gaan.
omdat meerdere threads dezelfde waarde kunnen ophalen en een context switch kan plaatsvinden tussen select en update. Les 1 van concurrent programming. :)
Dan had ik dus een te hoge dunk van transactions... Klopt ook wel wat je zegt. Er is geen garantie dat transactions netjes achter elkaar uitgevoerd worden of dat de bewerking van de ene uberhaupt nog zichtbaar wordt als er al een nieuwe transaction uitgevoerd is.
Tenzij je dus idd de transactions verplicht serieel maakt. Maar systemen die geen sequence/identity aanbieden, bieden dat soort transaction-control-instellingen vast ook niet :)
Over het algemeen is identity makkelijker maar minder flexibel (en dat is met bijna alles zo ;))
Ik vind de postgresql alias-oplossing ook wel geinig. Je maakt dan een tabel (zie eerder voorbeeld) met een SERIAL-kolom en daar wordt automatisch een unieke sequence bij gemaakt (tabelnaam_kolomnaam_seq oid), die als je de tabel of kolom dropt ook weer gedropped wordt.
dit zul je me even moeten uitleggen. Ik begrijp dat bij verschillende nextval calls de vorige values niet meer bekend zijn (goh ;)) maar als ik insert en daarna een scalar query, bv SELECT mysequence.CURRVAL FROM DUAL; doe (oracle) waarom zou dat niet de juiste waarde opleveren die is gebruikt in de insert?
Ik heb iig van een van de PostgreSQL-ontwikkelaars (Tom Lane) de garantie gekregen dat het daar werkt zoals EfBe hier al zegt (SELECT curval('sequence_naam') dan).
Binnen de connectie blijft de curval kloppen ten op zichte van de laatste nextval-call in die connectie (ik weet niet precies wat er gebeurt als er geen nextval plaatsgevonden heeft, kan zijn dat de 'huidige waarde' van tijdens de connectie-start dan genomen wordt). Dus als je nextval gebruikt voor een nieuwe waarde (bijv via het default-statement) kan je best honderd keer curval roepen zonder dat de waarde wijzigt, maar de volgende nextval is niet perse "curval + 1".
En ik kan me niet echt voorstellen dat dat bij andere dbms-en anders werkt, wellicht dat je dan nog "connectie" af en toe moet vervangen door "transactie".
Ik geloof dat ik het zei en hij mijn voorbeeld aanhaalde. Of andersom oid :)
Dat terzijde, ik snap nu wat je bedoelt. In Oracle kun je natuurlijk een default constraint aanmaken die een functie aanroept, maar ook daar heb je als nadeel dat je dan de waarde die is geinsert niet weet.
Ik had het opgelost toen door een sequence aan te maken en met een before-insert-trigger een waarde in het nieuwe record te stoppen.
En dan kan je natuurlijk die sequence benaderen (zoals je zelf in een voorbeeld geeft) voor de waarde van het nieuwe record :)

[ Voor 17% gewijzigd door ACM op 22-11-2004 16:51 ]

Pagina: 1