2009-02-18 5 views
7

Gibt es eine Tsql-Abfrage, um zu ermitteln, welchen SQL Server-Identitätsspaltenwert er für die nächste Zeileneinfügung verwenden soll?Wie sagen Sie, welche nächste Identitätssäule wird?

Edited hinzufügen:

ich gelöscht und neu erstellt eine Tabelle mit

[personID] [int] IDENTITY(1,1) NOT NULL 

als Teil meiner CREATE TABLE-Befehl. Ich habe auch versucht, Identitätsspalten neu zu erstellen, während alle Informationen in dieser Tabelle entfernt wurden, und das hat nicht immer funktioniert. Es hat mich dazu gebracht, mich zu fragen, ob es eine Möglichkeit gibt, zu sehen, was SQL für die nächste Identitätsspaltennummer erwartet.

+0

Nicht, dass ich weiß, aber warum willst du wissen? Was ist das große Bild Problem? – colithium

+0

Wenn Sie eine schnelle Spülung der Tabelle wünschen, setzt 'truncate table' automatisch alle Identitätsspalten zurück – SWeko

Antwort

10

Nein, es gibt keine garantiert Art und Weise (obwohl Sie sicher, was der könnte nächste Wert herausfinden können, sein, könnte ein anderer Befehl gehen und es verwenden, bevor Sie eine davon Gebrauch machen können). Der einzige garantierte Wert, den Sie abrufen können, ist der zuvor eingegebene Identitätswert über SCOPE_IDENTITY() (der den Identitätswert zurückliefert, der zuletzt für den aktuellen Bereich generiert wurde).

Es ist fraglich, aus welchem ​​Grund man den Wert vorher kennen müsste (bei Verwendung einer automatisch inkrementierten Spalte mit gesetzter Identität).

Wenn Sie den Wert vorher wissen müssen, dann empfehle ich, die IDs selbst zu generieren. Sie können dies tun, indem Sie eine IDs-Tabelle für den Tabellennamen eingeben, oder wenn Sie Probleme mit der Skalierbarkeit haben (und Transaktionen verwenden), können Sie eine ID-Tabelle für jede Tabelle haben, die eine ID benötigt, in die die ID eingefügt werden soll. und anschließend inkrementiert).

Oder Sie könnten eine GUID verwenden, und Sie könnten diese auf der Clientseite leicht generieren, bevor Sie sie an Ihre Datenbank senden.

+0

cool, FYI: http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity -vs-ident_current-retrieve-last-insert-identity-of-record/ – gbn

-1

Da Sie aus 1 säen und um 1 erhöhen (IDENTITY (1,1)), frage ich mich, ob Sie eine Prozedur erstellen können, in der Sie eine Variable wie "Select @@ IDENTITY + 1" oder ähnliches einstellen können Das.

15

Sie möchten wahrscheinlich SCOPE_IDENTITY nicht @@ IDENTITY verwenden, um es auf den Identitätswert im aktuellen Bereich zu beschränken. Dadurch wird vermieden, dass neue Identitätswerte von Triggern in andere Tabellen eingefügt werden und nicht in die Tabelle, in die Sie gerade eingefügt haben.

Aber man kann berechnen, was der nächste Identitätswert

SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable 

Das Problem ist, ist nicht garantiert, dass der Wert ist. Sie müssen eine Sperre haben, so dass andere Einfügungen auf dem Tisch bei der Ausführung verweigert werden, um sicherzustellen, dass der Wert korrekt ist. Auch nachdem Sie keine 32-Bit-Ganzzahlen mehr haben, weiß ich nicht, was die Logik ist. Ich weiß nicht, ob es rollt oder scheitert.

Edit: Ich habe gerade dies getestet (siehe unten für SQL) und es gibt nicht den richtigen Wert zurück, wenn keine Daten vorhanden sind. Und Nachsaat mit DBCC CHECK ('tablename', RESEED, 200) führte tatsächlich in dem nächsten Wert 201 nicht 200.

CREATE TABLE willtest (myid integer IDENTITY(1,1), myvalue varchar(255)) 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

INSERT INTO willtest (myvalue) 
VALUES ('1') 
INSERT INTO willtest (myvalue) 
VALUES ('2') 
INSERT INTO willtest (myvalue) 
VALUES ('3') 
INSERT INTO willtest (myvalue) 
VALUES ('4') 
INSERT INTO willtest (myvalue) 
VALUES ('5') 
INSERT INTO willtest (myvalue) 
VALUES ('6') 
INSERT INTO willtest (myvalue) 
VALUES ('7') 
INSERT INTO willtest (myvalue) 
VALUES ('8') 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

DBCC CHECKIDENT ('willtest', RESEED, 200) 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

INSERT INTO willtest (myvalue) 
VALUES ('200') 
INSERT INTO willtest (myvalue) 
VALUES ('201') 
INSERT INTO willtest (myvalue) 
VALUES ('202') 
INSERT INTO willtest (myvalue) 
VALUES ('203') 
INSERT INTO willtest (myvalue) 
VALUES ('204') 
INSERT INTO willtest (myvalue) 
VALUES ('205') 
INSERT INTO willtest (myvalue) 
VALUES ('206') 
INSERT INTO willtest (myvalue) 
VALUES ('207') 

SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest') 

SELECT * FROM willtest 

DROP TABLE willtest 
+0

An dieser Stelle können wir nicht einmal entscheiden, ob SCOPE_IDENTITY geeigneter ist als @@ IDENTITY. Oder wenn diese überhaupt anwendbar sind. – MarlonRibunal

+0

Dieser Teil reagierte auf den Vorschlag von casperOne. Nachdem die Frage bearbeitet wurde, ist das eigentliche Problem interessanter. –

+0

Sie brauchen nicht 'FROM Mytable' in Ihrer ersten Abfrage –

-1

Verwenden GUID Spalten für Ihren Primärschlüssel ist. Wenn Sie nicht Milliarden von Datensätzen und Tausende von Anfragen pro Sekunde haben, werden Sie wahrscheinlich den Leistungsunterschied nicht bemerken.Aber es sei denn, Sie verbringen viel zu viel Zeit mit dummen Problemen wie diesem, werden Sie den Unterschied in Ihrem Stresslevel und Ihrer Lebenserwartung bemerken.

+1

ich bitte um zu unterscheiden; Leistungsprobleme können auftreten, selbst wenn es etwa hunderttausend Datensätze und sehr wenige Anforderungen gibt. Siehe diese Frage, zum Beispiel: http://stackoverflow.com/questions/1703303/sum-group-performance-and-the-primary-key. Wir haben vor ein paar Jahren alles von Identitäten zu GUIDs verschoben und fangen an, diesen Schritt zu bereuen ... – Heinzi

+2

Jetzt benutze GUID nicht als PK, außer du weißt, was du tust 2. Mach es nicht Clustered (siehe Punkt 1) – gbn

+0

beantwortet nicht wirklich die Frage –

4

Dieses Stück von SQL Sie die nächste Identität Spalte Wert geben (es wahrscheinlich viele Gründe, nicht zu wiederholen, diese Schnipsel in der Produktion Code sind) gibt

declare @nextid int; 
declare @previousid int; 

begin tran 

insert into dbo.TestTable (Col1) values ('11'); 
select @nextid = SCOPE_IDENTITY(); 

rollback tran 

select @previousid = @nextid -1 
DBCC CHECKIDENT('dbo.TestTable', RESEED, @previousid); 
select @nextid 

diese Stackoverflow Frage einige zusätzliche Informationen - sql-identity-autonumber-is-incremented-even-with-a-transaction-rollback

0
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable 
+1

Dies berücksichtigt nicht entfernte Zeilen ... – HerbalMart

+0

Es berücksichtigt auch nicht, dass jemand absichtlich die nächste Seed-Nummer geändert hat, was ist, was ich gerade bin interessiert an heute. –

+0

Ich bin mir nicht sicher, ob dies für eine Datenbankversion spezifisch ist, aber ich bin SQL Server 2008 R2, und meine funktionierte gut, es ehrte DBCC reseed, und gab mir die richtigen Werte. @HerbalMart Es funktioniert basierend auf Ident_Current und gibt Ihnen korrekte Werte, selbst wenn Sie einige Zeilen entfernt haben. – Niraj

Verwandte Themen