Einfügen von Zeilen in eine Tabelle mit nur einer IDENTITY-Spalte

83

Ich habe einen Tabellenadministrator mit nur einer Spalte, adminId, die der Primärschlüssel ist. Aufgrund von Geschäftsregeln muss es so sein.

Ich möchte ein für alle Mal verstehen, wie ich gespeicherte Prozeduren schreiben kann, die Werte in solche Tabellen einfügen. Ich verwende SQL Server und T-SQL und habe versucht, SCOPE_IDENTITY () zu verwenden, aber das funktioniert nicht, da die Tabelle INSERT_IDENTITY auf false oder off hat.

Ich möchte wirklich keinen Dummy-Wert einfügen, nur um eine neue Zeile einfügen zu können. Vielen Dank!

Phil
quelle
1
Zur Verdeutlichung: Ihre Frage lautet "Wie füge ich Zeilen in eine SQL Server-Tabelle mit einer einzelnen IDENTITY-Spalte ein"?
Gbn
Ja, Sie haben Recht, danke für die Klarstellung
Phil
2
Für Leute, die hier landen, wurde dies schon einmal gefragt und die richtige Antwort ist hier: stackoverflow.com/questions/850327/…
BJury

Antworten:

140

Wenn Sie eine Spalte haben, die eine IDENTITÄT ist, tun Sie dies einfach

INSERT MyTable DEFAULT VALUES;  --allows no column list. The default will be the IDENTITY
SELECT SCOPE_IDENTITY();

Wenn Sie keine Identität haben, können Sie diese dann festlegen? Dies ist der beste Weg .. und verwenden Sie die SQL oben.

Wenn nicht, möchten Sie eine neue Zeile einfügen

INSERT MyTable (admidid)
OUTPUT INSERTED.admidid --returns result to caller
SELECT ISNULL(MAX(admidid), 0) + 1 FROM MyTable

Anmerkungen:

  • Unter hoher Last kann die MAX-Lösung mit Duplikaten ausfallen
  • SCOPE_IDENTITY ist nach der Tat, nicht vor
  • SCOPE_IDENTITY funktioniert nur mit einer IDENTITY-Spalte. Das Gleiche gilt für jede Idiotie mit IDENT_CURRENT
  • Die Ausgabeklausel ersetzt SCOPE_IDENTITY für die MAX-Lösung
gbn
quelle
1

Sie müssen die IDENTITY_INSERT zu Ihrer select-Anweisung hinzufügen:

SET IDENTITY_INSERT MyTable ON

INSERT INTO MyTable
(AdminCol)

SELECT AdminColValue

 FROM Tableb

Wenn Sie fertig sind, denken Sie daran

SET IDENTITY_INSERT MyTable OFF

Hier ist eine gute Beschreibung der Funktionsweise von BOL: http://msdn.microsoft.com/en-us/library/aa259221(SQL.80).aspx

DataWriter
quelle
Soll ich das so machen: SET IDENTITY_INSERT Administrator ON INSERT INTO Administrator (SCOPE_IDENTITY ()) SET IDENTITY_INSERT Administrator OFF?
Phil
Ja. Das ist alles was Sie tun müssen. SET ON, schreiben Sie Ihren Code, SET OFF am Ende.
DataWriter
Ich denke nicht, dass dies die richtige Antwort ist. Wenn es sich um eine Identitätsspalte handelt, sollten Sie keine Werte hinzufügen. Die akzeptierte Antwort ist die richtige Antwort.
Mmm
0

@Phil: Meinst du nicht, dass deine Tabelle zwei (2) Spalten hat, die automatisch inkrementierende PK-Spalte und eine AdminName-Spalte? Wenn der AdminName nur eine Spalte enthält, ist der AdminName die PK, und Sie können eine Zeichenfolge natürlich nicht automatisch inkrementieren. Erwarten die Geschäftsregeln, dass Sie einen vollqualifizierten Windows-Benutzernamen zum Primärschlüssel machen? Das wäre sinnvoll und sinnvoll, da Sie dann keinen alternativen eindeutigen Index für die Spalte AdminName benötigen würden.

Wenn Ihre Tabelle jedoch zwei Spalten enthält, nicht eine:

In SQLServer ist die automatische Inkrementierung Teil der Tabellen- / Spaltendefinition. Sie definieren die Spalte als Ganzzahl und machen sie dann auch zu einer Identitätsspalte, wobei Sie das Inkrement angeben, normalerweise 1, aber es kann 2 oder 5 oder 10 oder was auch immer sein. Um eine Zeile einzufügen, fügen Sie einfach die anderen Spaltenwerte ein und tun nichts mit der PK-Spalte:

insert into T
(foo)   -- column(s) list
values('bar') -- values list

Ihr gespeicherter Prozess, der die Einfügung ausführt, kann SCOPE_IDENTITY zu einem RETURN-Wert machen, oder SCOPE_IDENTITY kann als OUT-Parameter an den Client zurückgegeben werden.

PS SCOPE_IDENTITY () gibt den zuletzt generierten automatisch inkrementierten Identitätswert im aktuellen Bereich zurück. Es wird nicht der nächste Identitätswert generiert.

BEARBEITEN:

Vermutlich enthält Ihre Administratortabelle eine Reihe von Administratoren. Wenn jedoch keine anderen Spalten als die ganzzahlige Primärschlüsselspalte vorhanden sind, können die Administratoren nicht identifiziert werden. Sie können sie nur voneinander unterscheiden. Das bringt dich überhaupt nicht weit. Aber wenn Ihre Administrator-Tabelle eine der folgenden Strukturen hatte:

ID   INTEGER PRIMARY KEY AUTOINCREMENT
windowsusername   varchar(50)  (unique index)

ODER

windowsusername varchar(50) primary key

Sie könnten auf die Administratortabelle aus anderen Tabellen verweisen, und die Fremdschlüssel wären BEDEUTEND. Und genau das fehlt einer Tabelle, die aus einer einzelnen Ganzzahlspalte besteht - Bedeutung.

Mit zwei Spalten können Sie dann eine gespeicherte Prozedur ausführen lassen:

insert into Administrators
(windowsusername)
values('mydomain\someusername');
return SCOPE_IDENTITY();

und Ihr Client-Programm würde als Rückgabewert die automatisch inkrementierte ID zurückerhalten, die automatisch generiert und der neu eingefügten Zeile zugewiesen wurde. Dieser Ansatz ist die übliche Praxis, und ich würde sogar sagen, dass er als "Best Practice" gilt.

PS Sie erwähnen, dass Sie nicht wussten, wie man "einen Wert einfügt", wenn Sie "nichts einzufügen hatten". Da gibt es einen Widerspruch. Wenn Sie nichts einzufügen haben, warum einfügen? Warum würden Sie beispielsweise einen neuen KUNDENDATEN erstellen, wenn Sie absolut nichts über den Kunden wissen? Nicht ihr Name, ihre Stadt, ihre Telefonnummer, nichts?

Tim
quelle
2
Meine Tabelle hat EINE Spalte, adminId, die ein inkrementeller int-Wert ist
Phil
Das ist das seltsamste Design, das ich je gesehen habe, und ich bin seit über 20 Jahren im Geschäft und habe in meiner Zeit einige seltsame Dinge gesehen. Ihre Frage lautet also: Wie fügen Sie in eine Tabelle ein, die nur eine Primärschlüsselspalte enthält, die als automatisch inkrementierende Identitätsspalte definiert ist, wenn die Tabelle diese PK-Spalte und nur diese PK-Spalte enthält, keine anderen Spalten.
Tim
Wofür ist die Gegenstimme? Irgendwo ein sachlicher Fehler oder eine Meinung über den Mangel an Verdienst des Entwurfs?
Tim
1
Nur um die Gründe für das DB-Design zu verdeutlichen. Wir haben Benutzer in einer Tabelle. Wenn zwischen Benutzern und Administratoren eine Beziehung besteht; Sie werden als Admins behandelt. Es gibt nichts mehr in der Admin-Tabelle zu behalten als die tatsächliche eindeutige ID. Die "echten" Daten befinden sich in der Benutzertabelle und in der Has-Relation (mit Zeitstempeln und wer gewährt usw.).
Phil
1
@Phil: Sie verwenden also eine Tabelle und eine Fremdschlüsselbeziehung, um auszudrücken, was eine einfache Boolesche / Bit-Spalte bewirken kann. Möglicherweise können Sie Ihrer Tabelle keine solche Bitspalte hinzufügen und müssen eine Problemumgehung finden. But an autoincrementing integer whose autoincrementation must be disabled is a poor solution.Sie benötigen lediglich eine parallele Tabelle mit einer Eins-zu-Eins-Beziehung zur Benutzertabelle. In dieser Tabelle erstellen Sie eine Bitspalte. Wenn diese Spalte wahr ist, bedeutet dies, dass der Benutzer-admin hat. Reinigen. Standard. Design.
Tim