2010-11-02 9 views
11

Ich benutze SQL Server und wenn ich eine neue Tabelle erstellen, mache ich ein spezifisches Feld ein Autoinkrement Primärschlüssel. Das Problem ist, dass einige Leute mir gesagt haben, dass das Feld ein automatisches Inkrement für den Primärschlüssel bedeutet, wenn man einen Datensatz löscht (sie interessieren sich nicht für die Autoinkrementierungsfeldnummer), das Feld erhöht sich also irgendwann - wenn der Typ meines Feldes ist Integer zum Beispiel - der Bereich von Integer wird total verbraucht und ich werde in Schwierigkeiten geraten. Also sagen sie mir, dass ich dieses Feature nicht mehr benutzen soll.Auto-Inkrement-Funktion in der Datenbank

Die beste Lösung ist, dies durch den Code zu machen, indem ich das Maximum meines Primärschlüssels erhalte. Wenn der Wert dann nicht existiert, ist das Maximum 1 anders weise max + 1.

Haben Sie Vorschläge zu diesem Problem? Kann ich die Autoinkrementierungsfunktion verwenden?

ich auch die Fälle wissen will, was nicht bevorzugt ist Autoinkrement zu verwenden, um die Alternativen ..und ...

Note :: diese Frage allgemein zu allen DBMS nicht spezifisch, ich will ist, dies wissen true auch für DBMS wie ORACLE, Mysql, INFORMIX, ....

Vielen Dank.

+4

Nun, was ist das Problem, wenn es "Löcher" in der Reihenfolge der PK-Nummern gibt? Wen interessiert das? – zerkms

+0

gehen Sie für UniqueIdentifier :) –

+2

@Serkan - das ist ein Phantom-Problem, siehe Argumente unten für warum das Problem nicht existiert. "UniqueIdentifier" sollte damit sicherlich nicht als Motivation genutzt werden. Es ist ein 16-Byte-Wert, der viermal mehr Speicherplatz verbraucht als ein "int", was in den allermeisten Fällen akzeptabel ist, und doppelt so viel wie ein 'bigint', der fast immer akzeptabel ist, aber normalerweise nicht notwendig ist. –

Antwort

11

Sie sollten Identitätsspalten verwenden. Der bigint Datentyp kann Werte bis zu 2^63-1 (9,223,372,036,854,775,807) speichern. Ich glaube nicht, dass Ihr System diesen Wert bald erreichen wird, auch wenn Sie viele Datensätze einfügen und löschen.

Wenn Sie die Methode, die Sie vorschlagen, richtig implementieren, werden Sie mit einer Menge von Sperrproblemen enden. Andernfalls müssen Sie mit Ausnahmen umgehen, die aufgrund von Constraint-Verletzung (oder noch schlimmer - nicht eindeutige Werte geworfen werden, wenn keine Primärschlüsseleinschränkung vorliegt).

+3

+1.Vergessen Sie auch nicht, dass Sie immer noch all diese "Löcher" haben werden, wenn Sie die Max + 1 Route gehen - das würde nur einen Unterschied machen, wenn Sie nur den letzten Eintrag löschen. – AviD

+1

Sie können auch Rassenbedingungen haben es falsch. – HLGEM

+0

@HLGEM :: was meinst du unter Rennbedingungen hier ??? –

3

Verwenden Sie weiterhin die Identitätsfunktion mit PK in SQL Server. In Mysql gibt es auch Auto-Inkrement-Funktion. Machen Sie sich keine Sorgen darüber, dass Ihnen der Integer-Bereich ausgeht. Sie werden keinen Speicherplatz auf der Festplatte mehr haben, bevor das passiert.

3

Die von ihnen vorgeschlagene Lösung kann und wird höchstwahrscheinlich ein Nebenläufigkeits- und/oder Skalierbarkeitsproblem verursachen. Wenn zwei Sitzungen die Max-Methode verwenden, die Sie gleichzeitig beschreiben, können sie die gleiche Nummer eingeben und beide versuchen, sie gleichzeitig hinzuzufügen. Dies wird eine Constraint-Verletzung verursachen.

Sie können dieses Problem umgehen, indem Sie die Tabelle sperren oder Ausnahmen abfangen und immer wieder einfügen .. aber das ist ein wirklich schlechter Weg, Dinge zu tun. Das Sperren verringert die Leistung und verursacht Probleme mit der Skalierbarkeit (und wenn Sie so viele Datensätze planen, dass Sie befürchten müssen, dass ein int übergelaufen ist, benötigen Sie Skalierbarkeit).

Identitätsfelder sind atomare Operationen. Zwei Sitzungen können nicht das gleiche Identitätsfeld erstellen, daher ist dieses Problem bei der Verwendung nicht vorhanden.

Wenn Sie Bedenken haben, dass ein Identitätsfeld möglicherweise überläuft, verwenden Sie einen größeren Datentyp, z. B. bigint. Es wäre schwierig, genügend Datensätze zu generieren, um das zu überfließen.

Jetzt gibt es gültige Gründe, kein Identity-Feld zu verwenden, aber das ist keiner von ihnen.

8

Ein int-Datentyp in SQL Server kann Werte von -2.147.483.648 bis 2.147.483.647 enthalten.

Wenn Sie Ihre Identitätsspalte mit -2.147.483.648, z. FooId identity(-2,147,483,648, 1) dann haben Sie über 4 Milliarden Werte mit zu spielen.

Wenn Sie wirklich, dass dies noch nicht genug ist, könnten Sie ein bigint verwenden, die Werte von -9.223.372.036.854.775.808 durch 9.223.372.036.854.775.807 halten kann, aber das ist fast übertrieben sein garantiert. Selbst bei großen Datenmengen und/oder einer großen Anzahl von Transaktionen haben Sie wahrscheinlich entweder keinen Speicherplatz mehr oder verbrauchen die Lebensdauer Ihrer Anwendung, bevor Sie die Identitätswerte bei Verwendung einer int und fast sicher unter Verwendung einer bigint ausschöpfen.

Zusammenfassend sollten Sie eine Identitätsspalte verwenden und Sie sollten sich nicht um Lücken in den Werten kümmern, da a) Sie genügend Kandidatenwerte haben und b) eine abstrakte Zahl ohne logische Bedeutung ist.

Wenn Sie die vorgeschlagene Lösung implementieren und der Code die nächste Identitätsspalte ableitet, müssen Sie die Parallelität berücksichtigen, da Sie den Zugriff auf den aktuellen maximalen Identitätswert zwischen zwei konkurrierenden Transaktionen synchronisieren müssen. In der Tat können Sie am Ende eine erhebliche Leistungseinbuße einführen, da Sie zuerst den Maximalwert lesen, berechnen und dann einfügen müssen (ganz zu schweigen von der zusätzlichen Arbeit, die bei der Synchronisierung gleichzeitiger Transaktionen erforderlich ist). Wenn Sie jedoch eine Identitätsspalte verwenden, wird die Parallelität für Sie von der Datenbank-Engine gehandhabt.

+0

ist dies der Fall in Mysql und Informix DBMSs auch ,, oder nicht –

+0

Sekunde, was Sie mit abstrakten Nummer ??? –

+1

mysql/informix - keine Ahnung! Sie fragte nach SQL-Server ... –

1

ich GEGEN mit der Identität/Auto-Zuwachs raten würde, denn:

  • Es Implementierung ist in SQL Server 2005/2008 gebrochen. Read more

  • Es funktioniert nicht gut, wenn Sie ein ORM verwenden, um Ihre Datenbank Objekten zuzuordnen. Read more

Ich würde empfehlen Ihnen die Hallo/Lo-Generator zu verwenden, wenn Sie in der Regel Ihre Datenbank durch ein Programm zugreifen und hängen nicht Insert-Anweisungen manuell an die DB auf Senden. Sie können mehr darüber im zweiten Link lesen.

+1

eine weitere Falle von ORMs! :-) –

+0

Das ist eine andere Diskussion :) Aber ich sehe das nicht wirklich als Falle. Die Vorteile überwiegen, dass marginaler Nachteil – Trygve

+0

ja ich alle meine Tabellen Klassen in der Datenzugriffsschicht zuordnen, ist die Verwendung von Autoinkrement in diesem Fall wird ein großes Problem sein. –