2012-12-21 7 views
9

Ich mag Einfügen von Zeilen in eine Tabelle einfügen, die einen einzigartigen, nicht automatisch inkrementierte Primärschlüssel hat.Wie ein auto_increment Schlüssel in SQL Server-Tabelle

Gibt es eine native SQL-Funktion die letzte Schlüssel zu bewerten und erhöhen sie oder muss ich es in zwei Schritten zu tun haben:

key = select max(primary.key) + 1 

INSERT INTO dbo.TABLE (primary.key, field1, fiels2) VALUES (KEY, value1, value2) 
+3

Meinst du, du hast eine ['IDENTITY'-Spalte] (http://msdn.microsoft.com/en-us/library/ms186775.aspx) auf dem Tisch? Wenn ja, welches genaue Problem haben Sie, das nicht in der Dokumentation oder den [vielen Fragen] (http://stackoverflow.com/search?q=sql+identity) auf dieser Seite über ihre Verwendung diskutiert wird? In einem Kommentar unten erwähnen Sie einen Fehler, aber Sie haben nicht genau gesagt, was es ist. Im Idealfall zeigen Sie bitte Ihr 'CREATE TABLE'-Skript, Ihre' INSERT'-Anweisung und die resultierende Fehlermeldung an. – Pondlife

+0

Dieser Thread hat alle meine Kopfschmerzen gelöst und Code wird zurück kompiliert. Warum ppl hat das abgelehnt? –

Antwort

10

nach zu urteilen Sie Kommentare im gesamten, haben Sie einen Primärschlüssel auf dem Tisch, die nicht eine Identitätsspalte ist.

Wenn Ihre Version von SQL Server SQL 2012 ist, sollten Sie in Sequenzen aussehen: http://msdn.microsoft.com/en-us/library/ff878091.aspx

In anderen Versionen müssen Sie entweder die Tabelle mit der Identity-Eigenschaft neu erstellen (http://msdn.microsoft.com/en -us/library/aa933196 (v = sql.80) .aspx) für die Primärschlüsselspalte oder verwenden Sie einen zweistufigen Ansatz.

Wenn Sie mit dem zweistufigen Ansatz gehen Sie müssen sicherstellen, dass gleichzeitig laufende Einsätze nicht den gleichen neuen Wert am Ende mit. Der einfachste Weg, dies zu tun, ist dies durch die Auswahl und der Einsatz in einen Wert kombiniert und den serializable Tabellenhinweis verwendet:

CREATE TABLE dbo.Tbl1(id INT PRIMARY KEY, val1 INT, val2 INT) 

INSERT INTO dbo.Tbl1(id, val1, val2) 
VALUES((SELECT ISNULL(MAX(id)+1,0) FROM dbo.Tbl1 WITH(SERIALIZABLE, UPDLOCK)), 42, 47); 

SELECT * FROM dbo.Tbl1; 
+0

DANKE !!! Jetzt gibt es eine Lösung, es ist keine Funktion, aber ich kann mit einer Unterfrage fertig werden, besser als in zwei Schritten. Vielen Dank. –

+0

'SERIALIZABLE' ist äquivalent zu' HOLDLOCK' und ist ein guter Start, ist aber * nicht genug *. Ihre Abfrage kann weiterhin mit hoher Parallelität fehlschlagen. Sie müssen "UPDLOCK, TABLOCKX" hinzufügen. Die Teile einer Abfrage werden im Laufe der Zeit ausgeführt, und Sperren werden im Laufe der Zeit erworben - so kommt der 'INSERT' nach dem' SELECT'. Zwei Clients können gleichzeitig mit vollständig kompatiblen Lesesperren "AUSWÄHLEN", dann wird der zweite Block blockiert, während der erste zu einem "UPDLOCK" für seinen "INSERT" konvertiert wird, dann hat der zweite den alten Wert, sobald der Block ist Über. Sie brauchen die SELECT-Taste, um alle Leser ** zu blockieren! – ErikE

+1

Letztendlich ist dieses 'SELECT max() + 1'-Muster keine bewährte Methode und kann nicht empfohlen werden. Identitätsspalten existieren genau aus diesem Grund. Benutze sie. – ErikE

17

Da es automatisch generiert ist, es einfach nicht bieten:

INSERT INTO bo.TABLE (field1, fiels2) VALUES (value1, value2) 

-Update: Das wird funktionieren, wenn Ihre Spalte eine IDENTITY Spalte ist.

explizite Werte zu einer Identitätsspalte zu liefern, Sie haben, dies zu tun:

set identity_insert bo.TABLE on 

INSERT INTO bo.TABLE (primary_key, field1, fiels2) VALUES ((SELECT ISNULL(MAX(id) + 1, 0) FROM bo.Table), value1, value2) 

set identity_insert bo.TABLE off 

Aber es gibt keinen zwingenden Grund, es auf diese Weise zu tun.

+0

Ich habe es versucht, wirft einen Constraint-Fehler, ich muss den Wert bereitstellen. –

+1

Bitte poste den Fehler .... und deine Tabellendefinition. –

+0

Verletzung der PRIMARY KEY-Einschränkung 'pk_bo'. Kann keinen doppelten Schlüssel in das Objekt 'dbo.bo' einfügen. Der doppelte Schlüsselwert ist (921, 0, 2012). –

3

Meiner Meinung nach ist die beste Antwort Tisch zu fixieren, so dass die PK-Säule ist eine Identitätsspalte (Bitte beachten Sie meine Kommentare zu der Antwort von Sebastian Meine, warum Ihre aktuell ausgewählte Antwort nicht die beste ist.) Die einzige Möglichkeit, aus einem bestehenden PK eine Identitätsspalte zu machen, besteht darin, die Tabelle auszutauschen. Ungefähr:

Sie haben jetzt eine Tabelle, die eine Identitätsspalte mit einem gruppierten PK darauf hat. Du kannst dazu kein Problem einfügen. Nicht mehr Concurrency Probleme und dummen SELECT Max() + 1 Junk, dass so leicht zu bekommen falsch ist.

+0

+1 natürlich, wenn dies ein aktives System ist, möchten Sie dies in einer expliziten Transaktion tun. Andernfalls besteht die Gefahr, dass nach dem 'INSERT', aber vor dem Umbenennen einige Daten in' YourOriginalTable' gelangen. –

+0

Danke Aaron, das ist ein guter Fang. Behoben (denke ich). – ErikE

+0

Entschuldigung Es ist nicht mein Db, ich kann keine Änderungen vornehmen, es war Design mit einer ERP-Anwendung zu arbeiten. Müssen nur das Verfahren in der Frage erklärt, danke trotzdem. –

0

Tabelle erstellen, falls nicht vorhanden Emp ( eid int (10) nicht null Primärschlüssel auto_increment, Name VARCHAR (45) nicht null, Alter int (5) default 20, Gehalt int (5) ) Insert in emp Werte (102, 'Ranjan', 21,450000);

Dann versuchen Sie unter SQL-Abfrage. Es wird automatisch die eid zur nächsten Nummer erhöhen.

in Werte von emp (Name, Gehalt) einfügen ('Lisma', 118500);

auswählen * aus emp;

Verwandte Themen