Ich habe einige Werte in eine Tabelle eingefügt. Es gibt eine Spalte, deren Wert automatisch generiert wird. In der nächsten Anweisung meines Codes möchte ich diesen Wert abrufen.
Kannst du mir sagen, wie ich es richtig mache?
Ich habe einige Werte in eine Tabelle eingefügt. Es gibt eine Spalte, deren Wert automatisch generiert wird. In der nächsten Anweisung meines Codes möchte ich diesen Wert abrufen.
Kannst du mir sagen, wie ich es richtig mache?
Antworten:
@@IDENTITY
ist nicht bereichssicher und bringt Ihnen die ID aus einer anderen Tabelle zurück, wenn Sie einen Insert-Trigger für die ursprüngliche Tabelle haben. Verwenden Sie immer SCOPE_IDENTITY()
So mache ich meine Speicherprozeduren für MSSQL mit einer automatisch generierten ID.
CREATE PROCEDURE [dbo].[InsertProducts]
@id INT = NULL OUT,
@name VARCHAR(150) = NULL,
@desc VARCHAR(250) = NULL
AS
INSERT INTO dbo.Products
(Name,
Description)
VALUES
(@name,
@desc)
SET @id = SCOPE_IDENTITY();
Dies funktioniert sehr gut in SQL 2005:
DECLARE @inserted_ids TABLE ([id] INT);
INSERT INTO [dbo].[some_table] ([col1],[col2],[col3],[col4],[col5],[col6])
OUTPUT INSERTED.[id] INTO @inserted_ids
VALUES (@col1,@col2,@col3,@col4,@col5,@col6)
Es hat den Vorteil, dass alle IDs zurückgegeben werden, wenn Ihre INSERT-Anweisung mehrere Zeilen einfügt.
Wieder keine sprachunabhängige Antwort, aber in Java geht es so:
Connection conn = Database.getCurrent().getConnection();
PreparedStatement ps = conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
try {
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
rs.next();
long primaryKey = rs.getLong(1);
} finally {
ps.close();
}
Wenn Sie mit Oracle arbeiten:
In Tabelle einfügen (Felder ....) Werte (Werte ...) RÜCKGABE (Liste der Felder ...) INTO (Variablen ...)
Beispiel:
INSERT IN PERSON (NAME) VALUES ('JACK') RETURNING ID_PERSON IN vIdPerson
oder wenn Sie von ... Java mit einem CallableStatement anrufen (sry, es ist mein Feld)
INSERT IN PERSON (NAME) VALUES ('JACK') RETURNING ID_PERSON IN?
und Deklarieren eines Autput-Parameters für die Anweisung
Es gibt keine Standardmethode (genauso wie es keine Standardmethode zum Erstellen von IDs mit automatischer Inkrementierung gibt). Hier sind zwei Möglichkeiten, dies in PostgreSQL zu tun. Angenommen, dies ist Ihr Tisch:
CREATE TABLE mytable (
id SERIAL PRIMARY KEY,
lastname VARCHAR NOT NULL,
firstname VARCHAR
);
Sie können dies in zwei Anweisungen tun, solange es sich um aufeinanderfolgende Anweisungen in derselben Verbindung handelt (dies ist in PHP mit Verbindungspooling sicher, da PHP die Verbindung zum Pool erst zurückgibt, wenn Ihr Skript fertig ist):
INSERT INTO mytable (lastname, firstname) VALUES ('Washington', 'George');
SELECT lastval();
lastval () gibt Ihnen den letzten automatisch generierten Sequenzwert an, der in der aktuellen Verbindung verwendet wird.
Die andere Möglichkeit besteht darin, die RETURNING- Klausel von PostgreSQL für die INSERT- Anweisung zu verwenden:
INSERT INTO mytable (lastname) VALUES ('Cher') RETURNING id;
Dieses Formular gibt eine Ergebnismenge wie eine SELECT- Anweisung zurück und ist auch praktisch, um jede Art von berechnetem Standardwert zurückzugeben.
Ein wichtiger Hinweis ist, dass die Verwendung von SQL-Abfragen von Anbietern zum Abrufen der zuletzt eingefügten ID sicher ist, ohne dass gleichzeitige Verbindungen befürchtet werden müssen.
Ich dachte immer, Sie müssten eine Transaktion erstellen, um eine Zeile einzufügen, und dann die zuletzt eingefügte ID AUSWÄHLEN, um zu vermeiden, dass eine von einem anderen Client eingefügte ID abgerufen wird.
Diese herstellerspezifischen Abfragen rufen jedoch immer die zuletzt eingefügte ID für die aktuelle Verbindung zur Datenbank ab . Dies bedeutet, dass die zuletzt eingefügte ID nicht von anderen Client-Einfügungen beeinflusst werden kann, solange diese ihre eigene Datenbankverbindung verwenden.
Für SQL 2005:
Angenommen, die folgende Tabellendefinition:
CREATE TABLE [dbo].[Test](
[ID] [int] IDENTITY(1,1) NOT NULL,
[somevalue] [nchar](10) NULL,
)
Sie können Folgendes verwenden:
INSERT INTO Test(somevalue)
OUTPUT INSERTED.ID
VALUES('asdfasdf')
Dies gibt den Wert der ID-Spalte zurück.
Auf der Website habe ich Folgendes herausgefunden:
SQL SERVER - @@ IDENTITY vs SCOPE_IDENTITY () vs IDENT_CURRENT - Abrufen der zuletzt eingefügten Identität des Datensatzes 25. März 2007 von pinaldave
SELECT @@ IDENTITY Gibt den letzten IDENTITY-Wert zurück, der für eine Verbindung erzeugt wurde, unabhängig von der Tabelle, die den Wert erzeugt hat, und unabhängig vom Umfang der Anweisung, die den Wert erzeugt hat. @@ IDENTITY gibt den zuletzt in Ihrer aktuellen Sitzung in eine Tabelle eingegebenen Identitätswert zurück. Während @@ IDENTITY auf die aktuelle Sitzung beschränkt ist, ist es nicht auf den aktuellen Bereich beschränkt. Wenn Sie einen Auslöser für eine Tabelle haben, der bewirkt, dass eine Identität in einer anderen Tabelle erstellt wird, erhalten Sie die zuletzt erstellte Identität, auch wenn es der Auslöser war, der sie erstellt hat.
SELECT SCOPE_IDENTITY () Gibt den letzten IDENTITY-Wert zurück, der für eine Verbindung und eine Anweisung im selben Bereich erzeugt wurde, unabhängig von der Tabelle, die den Wert erzeugt hat. SCOPE_IDENTITY () gibt wie @@ IDENTITY den zuletzt in der aktuellen Sitzung erstellten Identitätswert zurück, beschränkt ihn jedoch auch auf Ihren aktuellen Bereich. Mit anderen Worten, es wird der letzte Identitätswert zurückgegeben, den Sie explizit erstellt haben, und nicht jede Identität, die durch einen Trigger oder eine benutzerdefinierte Funktion erstellt wurde.
SELECT IDENT_CURRENT ('Tabellenname') Gibt den zuletzt in einer Tabelle erzeugten IDENTITY-Wert zurück, unabhängig von der Verbindung, die den Wert erstellt hat, und unabhängig vom Umfang der Anweisung, die den Wert erzeugt hat. IDENT_CURRENT ist nicht durch Umfang und Sitzung beschränkt. Es ist auf eine bestimmte Tabelle beschränkt. IDENT_CURRENT gibt den Identitätswert zurück, der für eine bestimmte Tabelle in einer Sitzung und einem Bereich generiert wurde.
Denken Sie daran, dass @@ IDENTITY die zuletzt erstellte Identität für Ihre aktuelle Verbindung zurückgibt, nicht unbedingt die Identität für die zuletzt hinzugefügte Zeile in einer Tabelle. Sie sollten immer SCOPE_IDENTITY () verwenden, um die Identität der kürzlich hinzugefügten Zeile zurückzugeben.
Welche Datenbank verwenden Sie? Soweit mir bekannt ist, gibt es dafür keine datenbankunabhängige Methode.
So habe ich es mit parametrisierten Befehlen gemacht.
MSSQL
INSERT INTO MyTable (Field1, Field2) VALUES (@Value1, @Value2);
SELECT SCOPE_IDENTITY();
MySQL
INSERT INTO MyTable (Field1, Field2) VALUES (?Value1, ?Value2);
SELECT LAST_INSERT_ID();
sql = "INSERT INTO MyTable (Name) VALUES (@Name);" +
"SELECT CAST(scope_identity() AS int)";
SqlCommand cmd = new SqlCommand(sql, conn);
int newId = (int)cmd.ExecuteScalar();
Frau SQL Server: Dies ist eine gute Lösung, auch wenn Sie mehr Zeilen einfügen:
Declare @tblInsertedId table (Id int not null)
INSERT INTO Test ([Title], [Text])
OUTPUT inserted.Id INTO @tblInsertedId (Id)
SELECT [Title], [Text] FROM AnotherTable
select Id from @tblInsertedId
Robs Antwort wäre die herstellerunabhängigste, aber wenn Sie MySQL verwenden , ist die integrierte LAST_INSERT_ID()
Funktion die sicherere und korrektere Wahl .
SELECT @@Scope_Identity as Id
Es gibt auch eine @ @ Identität, aber wenn Sie einen Auslöser haben, werden die Ergebnisse von etwas zurückgegeben, das während des Auslösers passiert ist, wobei scope_identity Ihren Bereich respektiert.
Eine umweltbasierte Oracle-Lösung:
CREATE OR REPLACE PACKAGE LAST
AS
ID NUMBER;
FUNCTION IDENT RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY LAST
AS
FUNCTION IDENT RETURN NUMBER IS
BEGIN
RETURN ID;
END;
END;
/
CREATE TABLE Test (
TestID INTEGER ,
Field1 int,
Field2 int
)
CREATE SEQUENCE Test_seq
/
CREATE OR REPLACE TRIGGER Test_itrig
BEFORE INSERT ON Test
FOR EACH ROW
DECLARE
seq_val number;
BEGIN
IF :new.TestID IS NULL THEN
SELECT Test_seq.nextval INTO seq_val FROM DUAL;
:new.TestID := seq_val;
Last.ID := seq_val;
END IF;
END;
/
To get next identity value:
SELECT LAST.IDENT FROM DUAL
In TransactSQL können Sie die OUTPUT-Klausel verwenden, um dies zu erreichen.
INSERT INTO my_table(col1,col2,col3) OUTPUT INSERTED.id VALUES('col1Value','col2Value','col3Value')
Einfachste Antwort:
command.ExecuteScalar()
Standardmäßig wird die erste Spalte zurückgegeben
Rückgabewert Typ: System.Object Die erste Spalte der ersten Zeile in der Ergebnismenge oder eine Nullreferenz (Nothing in Visual Basic), wenn die Ergebnismenge leer ist. Gibt maximal 2033 Zeichen zurück.
Von MSDN kopiert