[SQL] Key Violation

Pagina: 1
Acties:

  • Cryothic
  • Registratie: September 2001
  • Laatst online: 04-09-2024
Hee, ik heb een probleempje met het toevoegen van een record in een MS SQL SERVER Tabel.

Voordat ik een record toevoeg in de tabel kijk ik naar de maximale waarde van het sleutel veld, en daar tel ik 1 bij op.

Dat gaat allemaal goed, tot dat er een 2de gebruiker komt.
Als Gebruiker2 namelijk die maximale waarde vraagt op het moment dat Gebruiker1 net ook die waarde heeft opgevraagt, hebben ze dezelfde waarde.
Op het moment dat ze dus die records toevoegen, krijgt 1 van beide een key-violation.

Heeft iemand enig idee hoe dit op te lossen is? Het moet met SQL mogelijk zijn om een speciale Lock te plaatsen speciaal voor Key's, maar ik weet niet hoe dat werkt, en of dat de oplossing is.

Greetz.
Cryothic 8-)

Verwijderd

identity veld van maken?
code:
1
2
3
4
CREATE TABLE Whatever
(
  MyIncrementField integer IDENTITY (0, 1)
)

Verwijderd

Ik ken vier oplossingen:
1) Transactie gebruiken
2) Nieuwe ID pas ophogen als je daadwerkelijk de Post doet.
3) Lock
4) Autoincremental field gebruiken!

  • Pogostokje
  • Registratie: September 2001
  • Laatst online: 11-09 16:57

Pogostokje

* twiet *

Voordat ik een record toevoeg in de tabel kijk ik naar de maximale waarde van het sleutel veld, en daar tel ik 1 bij op. Dat gaat allemaal goed, tot dat er een 2de gebruiker komt.
Daar is een aparte functie voor, dat hoef je helemaal niet zelf te gaan doen. Maak van het veld een identity en het zal vanzelf gevuld worden met unieke (oplopende) waardes.

... ook ik heb soms per ongeluk gelijk.


Verwijderd

En als je dan toch in SQL server bezig bent, dan kun je ook wel een GUID veld maken; ziet ook cool uit: A422D-FF320-7C3EE-394E1-32DF5 :)

  • Cryothic
  • Registratie: September 2001
  • Laatst online: 04-09-2024
Op dinsdag 05 maart 2002 14:01 schreef hvdberg het volgende:
Ik ken vier oplossingen:
1) Transactie gebruiken
2) Nieuwe ID pas ophogen als je daadwerkelijk de Post doet.
3) Lock
4) Autoincremental field gebruiken!
Zou je dan ajb een voorbeeld kunnen geven van een transactie en een lock?
Want van die help in SQL Server zelf wordt ik niet echt wijzer.

Alvast bedankt allemaal

Verwijderd

Op dinsdag 05 maart 2002 14:03 schreef daxx909 het volgende:
En als je dan toch in SQL server bezig bent, dan kun je ook wel een GUID veld maken; ziet ook cool uit: A422D-FF320-7C3EE-394E1-32DF5 :)
Dat is nog es een goed design, een guid kiezen omdat het er zo "cool" uit ziet |:(

Verwijderd

Wat je ook kunt doen is een trigger gebruiken om een nieuw ID aan te maken..

Verwijderd

Dat is nog es een goed design, een guid kiezen omdat het er zo "cool" uit ziet
Nou, die key maakt SQL server voor jou en is dan wel wereldwijd uniek. Dit veel beter dan een nummertje; want in principe wil je toch een uniek iets?

Verwijderd

Op dinsdag 05 maart 2002 14:08 schreef daxx909 het volgende:
Nou, die key maakt SQL server voor jou en is dan wel wereldwijd uniek. Dit veel beter dan een nummertje; want in principe wil je toch een uniek iets?
Ik ben me er goed van bewust wat een guid is, ik ben alleen van mening dat je een *erg* slecht design hebt als je een guid hebt gekozen op basis van dat het er "cool" uit ziet, een identity veld hoeft van mij alleen maar voor die ene tabel waar ik 'm opzet uniek te zijn, dat sql server ook nummers kan genereren die wereldwijd uniek zijn leuk maar ik zie de toegevoegde waarde (zeker in dit geval) totaal niet.

Verwijderd

Daarnaast is de 'uniekheid' van een GUID niet verzekerd. Theoretisch gesproken is het mogelijk dat 2 verschillende computers hetzelfde GUID genereren.

GUID zijn daar ook helemaal niet voor bedoeld.

Kun je me uitleggen waarom een GUID beter is dan een nummertje? Zolang het maar uniek is maakt het imo geen ruk uit en is een nummertje juist beter/netter. Is ook makkelijker te sorteren enz.

Verwijderd

Bovendien is de GUID die SQL server genereerd (versie 7 tenminste) absoluut niet uniek want ik krijg het volgende:
code:
1
2
3
4
5
{00000000-0000-0000-0000-000000000001}
{00000000-0000-0000-0000-000000000002}
{00000000-0000-0000-0000-000000000003}
...
{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}

M.a.w. als je bij de laatste bent (128-bits integer) dan is dat harde schijfje allang vol hoor (waarschijnlijk haal je de bovengrens van 64-bits integers niet eens).

Hier sla je dus 16 bytes per record op terwijl 4 bytes meer dan voldoende zal blijken te zijn.

PS. Mag je het dan wel een GUID noemen? Global Unique is die dan namelijk niet!?

Verwijderd

Op dinsdag 05 maart 2002 14:01 schreef hvdberg het volgende:
Ik ken vier oplossingen:
1) Transactie gebruiken
2) Nieuwe ID pas ophogen als je daadwerkelijk de Post doet.
3) Lock
4) Autoincremental field gebruiken!
Ik ken er nog één:
Stored Procedures!

Ik heb de documentatie van SQL Server hier niet bij de hand: zoek eens bij BeginTrans o.i.d.

Wat voor client gebruik je (VB/ADO)?

  • Cryothic
  • Registratie: September 2001
  • Laatst online: 04-09-2024
Je bedoelt waar ik de database mee aanspreek?
Delphi.
:D

Bedankt, ik al ff kijken

Verwijderd

{00000000-0000-0000-0000-000000000001}
{00000000-0000-0000-0000-000000000002}
{00000000-0000-0000-0000-000000000003}
...
{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}
Dan doe je toch iets fout; 't moet 1 warboel zijn! :P
Zoiets: INSERT INTO tabel([ID]) VALUES(new_guid())

Verwijderd

Op dinsdag 05 maart 2002 14:54 schreef Cryothic het volgende:
Je bedoelt waar ik de database mee aanspreek?
Delphi.
:D

Bedankt, ik al ff kijken
Dat maakt het al een stuk makkelijker i.i.g. Maak je gebruik van ADO of BDE?

Er is hier heel veel te vinden over transactie verloop m.b.v. Delphi-client (BDE danwel ADO).

Verwijderd

Op dinsdag 05 maart 2002 14:57 schreef daxx909 het volgende:

[..]

Dan doe je toch iets fout; 't moet 1 warboel zijn! :P
Zoiets: INSERT INTO tabel([ID]) VALUES(new_guid())
Dan nog, wat is het nut: 12 bytes tegen 4 bytes. Het rekent langzamer, het kost meer opslag capaciteit, het ziet er niet logisch uit, de kans dat je 2 keer dezelfde GUID genereert kan aanwezig zijn terwijl dit niet wenselijk is en ook niet het geval is van een identy-field.

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Als je geen Identity wilt gebruiken kan je zoiets als dit doen:
Select @MaxLogID = ISNULL(MAX(log_ID),0)+1 FROM sma_Log

  • Goodielover
  • Registratie: November 2001
  • Laatst online: 18-08 11:34

Goodielover

Only The Best is Good Enough.

Creeer een tabel met sequences waarin je voor al je tabellen de laatst uitgegeven key bijhoudt en dan in je get-key procedure:
code:
1
2
3
4
5
6
7
8
9
update sequence
set    nummer = mummer +1
where  tabel = &tabelnaam;

select nummer
into   &new_key
from   sequence
wehere tabel = &tabelnaam;
commit;

Het eerste statement lockt ook direct de tabel dus je weet zeker dat jij het juiste nummer hebt.

  • Cryothic
  • Registratie: September 2001
  • Laatst online: 04-09-2024
Op dinsdag 05 maart 2002 15:04 schreef hvdberg het volgende:

Dat maakt het al een stuk makkelijker i.i.g. Maak je gebruik van ADO of BDE?

Er is hier heel veel te vinden over transactie verloop m.b.v. Delphi-client (BDE danwel ADO).
Ik gebruik BDE.

edit.
offtopic:
Hoe krijg ik trouwens enters in de ondertitel?
Pagina: 1