Ich habe einen SQL Server 2008-Server (Build 10.0.5500). Anfang dieser Woche habe ich dies für eine Tabelle ausgeführt , in der bereits Daten enthalten waren :
delete from dbo.table
go
dbcc checkident('dbo.table',reseed,0)
Wenn der Benutzer später einen neuen Datensatz erstellen wollte, wurde irgendwie eine ID von 0 in die ID-Spalte eingefügt, anstatt der 1, die SQL Server normalerweise eingibt, wenn Identität (1,1) für die ID konfiguriert ist.
Dies verursachte einige seltsame Probleme, aber das Löschen der Daten und das Ausführen des Reseeds führte erwartungsgemäß dazu, dass eine 1 eingefügt wurde. Ich kann das Problem nicht duplizieren.
Als Referenz ist hier das allgemeine Format für unsere Sicherungssps:
alter procedure dbo._TableSave
@pk_id int,
@field varchar(50)
as
if (@pk_id is null)
begin
set nocount on;
insert into dbo.Table
(
Field
)
values
(
@field
);
select scope_identity();
end
else
begin
update dbo.Table
set Field=@field
where PK_ID=@pk_id
select @pk_id
end
Weiß jemand, was dazu führen kann, dass SQL Server eine 0 in die ID einfügt, wenn es eine 1 sein sollte?
Wir fügen keine Daten in Identitätsspalten (mit aktivierter Identitätseinfügung ) irgendwo in der Anwendung ein.
quelle
CREATE TABLE dbo.[table] (id int identity(1,1));INSERT INTO dbo.[table] DEFAULT VALUES;DELETE FROM dbo.[table];dbcc checkident('dbo.table',reseed,0);INSERT INTO dbo.[table] OUTPUT inserted.* DEFAULT VALUES;DROP TABLE dbo.[table]
Ich schlage den folgenden Code vor, um dies zu verhindern:
(Anstelle des Codes, den Sie in Ihrer Frage gepostet haben)
Es sollte das "Nachsaaten auf 0" verhindern.
Erläuterung:
(Ich habe keine offizielle Dokumentation gefunden, die dies unterstützt ...)
Das Problem liegt in der Tabelle
sys.syscolpars
in einer Spalte mit dem Namenidtval
, die die Spalte enthält, die ALLE Informationen zur Identitätsspalte enthält.
Da die Tabelle eine Zeile für jede Spalte in der Datenbank (nicht nur die Identität Spalt) hat,
a
NULL
wird Wert in diesem Bereich eine Nichtidentität Spalte dar( im Gegensatz zu
sys.identity_columns
denen VerwendungenNULL
für eine neue \ trunkiert Tabelle).sys.syscolpars
verwendet ein anderes Verfahren zum Herstellen des Informationshaltes:es das uses
0x01000000010000000100000001
Formats (Beispiel der Identität (1,1) neu erstellt wird ),mit den linken 8 Stellen (Position 1-8 , nachdem die
0x
) fürLast_Value
,den nächsten 8 - stellig (Position 9-16 nach dem
0x
) fürincrement_value
,die nächsten 8 Ziffern (Position 17-24 nach dem
0x
) fürseed_value
,die 2. Ziffer von rechts ist mir ein Rätsel,
und die 1. Ziffer von rechts - sagt uns, ob es sich um eine neue Tabelle handelt (= 1 ) oder nicht!
zurück zu unserem Problem -
wenn
DBCC CHECKIDENT
es ausgeführt wird, prüft es,sys.identity_columns.last_value
ob dies der Fall ist,
NULL
und aktualisiert dann den neuen Wert vonsys.syscolpars.idtval
mit1
an der richtigen Position.sys.identity_columns.last_value
bleibtNULL
.Dadurch wird der nächste Insert-Identitätswert wie in einer neuen Tabelle behandelt.
(Ich gehe davon aus, dass dies
sys.identity_columns
unabhängig ist,sys.syscolpars
da das erste sofort aktualisiert wird und das letztere erst aktualisiert wird, nachdem ein Prüfpunkt durchgeführt wurde.)Da es keine Möglichkeit gibt,
sys.syscolpars
in Echtzeit abzufragen (es erfordert DAC), istmein Vorschlag die obige Bedingung, möglicherweise mit der Hinzufügung einer
ELSE
Klausel.Auch hier kann ich nicht garantieren, dass eine dieser Erklärungen wahr ist, aber es funktioniert :)
Wenn jemand genauere Informationen über die
DBCC CHECKIDENT
Hintergrundoperation hat,würde ich gerne erfahren, bitte teilen!
Viel Glück,
רועי גביש
quelle
Dieser Befehl bewirkt, dass der neue Identitätswert auf 0 gesetzt wird. Ich habe das gleiche Problem festgestellt.
dann wende ich so eine reseed identität auf 1 an
quelle