Wie bekomme ich die zuletzt eingefügte ID?


174

Ich habe diesen Code:

string insertSql = 
    "INSERT INTO aspnet_GameProfiles(UserId,GameId) VALUES(@UserId, @GameId)";

using (SqlConnection myConnection = new SqlConnection(myConnectionString))
{
   myConnection.Open();

   SqlCommand myCommand = new SqlCommand(insertSql, myConnection);

   myCommand.Parameters.AddWithValue("@UserId", newUserId);
   myCommand.Parameters.AddWithValue("@GameId", newGameId);

   myCommand.ExecuteNonQuery();

   myConnection.Close();
}

Wenn ich in diese Tabelle einfüge, habe ich eine auto_increment int-Primärschlüsselspalte mit dem Namen GamesProfileId. Wie kann ich die zuletzt eingefügte Spalte danach abrufen , damit ich diese ID zum Einfügen in eine andere Tabelle verwenden kann?

Antworten:


256

Wenn für SQL Server 2005+ kein Einfügetrigger vorhanden ist, ändern Sie die Einfügeanweisung (alle eine Zeile, hier aus Gründen der Übersichtlichkeit geteilt) in diese

INSERT INTO aspnet_GameProfiles(UserId,GameId)
OUTPUT INSERTED.ID
VALUES(@UserId, @GameId)

Für SQL Server 2000 oder wenn ein Einfügetrigger vorhanden ist:

INSERT INTO aspnet_GameProfiles(UserId,GameId) 
VALUES(@UserId, @GameId);
SELECT SCOPE_IDENTITY()

Und dann

 Int32 newId = (Int32) myCommand.ExecuteScalar();

5
OUTPUT INSERTED.IDkönnte im Falle eines aktiven Auslösers auf dem Tisch ein Problem erzeugen
armen

2
Hmm. Als ich dies versuchte, bekam ich eine Fehlermeldung: "Objektreferenz nicht auf eine Instanz eines Objekts festgelegt." obwohl es unmittelbar nach der Ausführung ausgeführt wird.
Khany

@ Khany hast du es behoben?
TuGordoBello

5
Die 'ID' in 'OUTPUT INSERTED.ID' ist übrigens der Primärschlüssel. Ich dachte, es sei ein zurückhaltendes Wort.
Danmbuen

1
@VoidKing: Wie kann ich das sagen .. du machst etwas falsch. Stellen Sie eine neue Frage mit Beispielcode, um Hilfe zu erhalten. Offensichtlich haben Sie mir gesagt, dass ich falsch
liege,

38

Sie können einen Befehl mit CommandTextgleich erstellen

INSERT INTO aspnet_GameProfiles(UserId, GameId) OUTPUT INSERTED.ID VALUES(@UserId, @GameId)

und ausführen int id = (int)command.ExecuteScalar.

Dieser MSDN-Artikel enthält einige zusätzliche Techniken.


6
string insertSql = 
    "INSERT INTO aspnet_GameProfiles(UserId,GameId) VALUES(@UserId, @GameId)SELECT SCOPE_IDENTITY()";

int primaryKey;

using (SqlConnection myConnection = new SqlConnection(myConnectionString))
{
   myConnection.Open();

   SqlCommand myCommand = new SqlCommand(insertSql, myConnection);

   myCommand.Parameters.AddWithValue("@UserId", newUserId);
   myCommand.Parameters.AddWithValue("@GameId", newGameId);

   primaryKey = Convert.ToInt32(myCommand.ExecuteScalar());

   myConnection.Close();
}

Diese üble Arbeit :)


vil? Ich denke, wir sollten grammatikalisch korrektere Antworten schreiben, um ehrlich zu sein
Zizzipupp

3

Ich hatte das gleiche Bedürfnis und fand diese Antwort ..

Dadurch wird ein Datensatz in der Firmentabelle (comp) erstellt. Dabei wird die in der Firmentabelle erstellte automatische ID erfasst und in eine Staff-Tabelle (staff) abgelegt, sodass die beiden Tabellen mit VIELEN Mitarbeitern mit EINER Firma verknüpft werden können. Es funktioniert auf meiner SQL 2008-Datenbank, sollte auf SQL 2005 und höher funktionieren.

===========================

CREATE PROCEDURE [dbo].[InsertNewCompanyAndStaffDetails]

 @comp_name varchar(55) = 'Big Company',

 @comp_regno nchar(8) = '12345678',

 @comp_email nvarchar(50) = 'no1@home.com',

 @recID INT OUTPUT

- Die ' @recID' wird verwendet, um die automatisch generierte ID-Nummer des Unternehmens zu speichern, die wir abrufen möchten

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- In der obigen Zeile wird eine temporäre Tabelle erstellt, in der die automatisch generierte ID-Nummer für die spätere Verwendung gespeichert ist. Es hat nur ein Feld 'tempID' und sein Typ INT ist der gleiche wie der von '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- Der ' OUTPUT eingefügt. Die obige Zeile wird verwendet, um Daten aus einem beliebigen Feld in dem Datensatz abzurufen, den sie gerade erstellt. Diese Daten, die wir wollen, sind die ID-Autonummer. Stellen Sie also sicher, dass der richtige Feldname für Ihre Tabelle angegeben ist. Mein Name lautet 'comp_id' . Dies wird dann in die zuvor erstellte temporäre Tabelle verschoben.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- In der obigen Zeile wird die zuvor erstellte temporäre Tabelle durchsucht, in der die benötigte ID gespeichert ist. Da diese temporäre Tabelle nur einen Datensatz und nur ein Feld enthält, wird nur die von Ihnen benötigte ID-Nummer ausgewählt und in ' @recID ' abgelegt . ' @recID ' hat jetzt die gewünschte ID-Nummer und Sie können sie so verwenden, wie Sie es möchten, wie ich sie unten verwendet habe.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

-- Hier bitteschön. Sie können in der Zeile 'OUTPUT insert.WhatEverFieldNameYouWant' nach Belieben greifen, die gewünschten Felder in Ihrer temporären Tabelle erstellen und darauf zugreifen, um zu verwenden, wie immer Sie möchten.

Ich habe ewig nach so etwas gesucht, mit dieser detaillierten Aufschlüsselung hoffe ich, dass dies hilft.


3

In reinem SQL lautet die Hauptanweisung wie folgt:

INSERT INTO [simbs] ([En]) OUTPUT INSERTED.[ID] VALUES ('en')

Eckige Klammern definieren die Tabellensimulationen und dann die Spalten En und ID, runde Klammern definieren die Aufzählung der zu initiierenden Spalten und dann die Werte für die Spalten, in meinem Fall eine Spalte und einen Wert. Die Apostrophe umschließen eine Schnur

Ich werde Ihnen meinen Ansatz erklären:

Es ist vielleicht nicht leicht zu verstehen, aber ich hoffe, dass es nützlich ist, mit der zuletzt eingefügten ID einen Überblick zu bekommen. Natürlich gibt es alternative einfachere Ansätze. Aber ich habe Gründe, meine zu behalten. Zugehörige Funktionen sind nicht enthalten, nur deren Namen und Parameternamen.

Ich verwende diese Methode für die medizinische künstliche Intelligenz. Die Methode prüft, ob die gewünschte Zeichenfolge in der zentralen Tabelle (1) vorhanden ist. Befindet sich die gewünschte Zeichenfolge nicht in der zentralen Tabelle "simbs" oder sind Duplikate zulässig, wird die gewünschte Zeichenfolge zur zentralen Tabelle "simbs" (2) hinzugefügt. Die zuletzt eingefügte ID wird verwendet, um die zugehörige Tabelle (3) zu erstellen.

    public List<int[]> CreateSymbolByName(string SymbolName, bool AcceptDuplicates)
    {
        if (! AcceptDuplicates)  // check if "AcceptDuplicates" flag is set
        {
            List<int[]> ExistentSymbols = GetSymbolsByName(SymbolName, 0, 10); // create a list of int arrays with existent records
            if (ExistentSymbols.Count > 0) return ExistentSymbols; //(1) return existent records because creation of duplicates is not allowed
        }
        List<int[]> ResultedSymbols = new List<int[]>();  // prepare a empty list
        int[] symbolPosition = { 0, 0, 0, 0 }; // prepare a neutral position for the new symbol
        try // If SQL will fail, the code will continue with catch statement
        {
            //DEFAULT und NULL sind nicht als explizite Identitätswerte zulässig
            string commandString = "INSERT INTO [simbs] ([En]) OUTPUT INSERTED.ID VALUES ('" + SymbolName + "') "; // Insert in table "simbs" on column "En" the value stored by variable "SymbolName"
            SqlCommand mySqlCommand = new SqlCommand(commandString, SqlServerConnection); // initialize the query environment
                SqlDataReader myReader = mySqlCommand.ExecuteReader(); // last inserted ID is recieved as any resultset on the first column of the first row
                int LastInsertedId = 0; // this value will be changed if insertion suceede
                while (myReader.Read()) // read from resultset
                {
                    if (myReader.GetInt32(0) > -1) 
                    {
                        int[] symbolID = new int[] { 0, 0, 0, 0 };
                        LastInsertedId = myReader.GetInt32(0); // (2) GET LAST INSERTED ID
                        symbolID[0] = LastInsertedId ; // Use of last inserted id
                        if (symbolID[0] != 0 || symbolID[1] != 0) // if last inserted id succeded
                        {
                            ResultedSymbols.Add(symbolID);
                        }
                    }
                }
                myReader.Close();
            if (SqlTrace) SQLView.Log(mySqlCommand.CommandText); // Log the text of the command
            if (LastInsertedId > 0) // if insertion of the new row in the table was successful
            {
                string commandString2 = "UPDATE [simbs] SET [IR] = [ID] WHERE [ID] = " + LastInsertedId + " ;"; // update the table by giving to another row the value of the last inserted id
                SqlCommand mySqlCommand2 = new SqlCommand(commandString2, SqlServerConnection); 
                mySqlCommand2.ExecuteNonQuery();
                symbolPosition[0] = LastInsertedId; // mark the position of the new inserted symbol
                ResultedSymbols.Add(symbolPosition); // add the new record to the results collection
            }
        }
        catch (SqlException retrieveSymbolIndexException) // this is executed only if there were errors in the try block
        {
            Console.WriteLine("Error: {0}", retrieveSymbolIndexException.ToString()); // user is informed about the error
        }

        CreateSymbolTable(LastInsertedId); //(3) // Create new table based on the last inserted id
        if (MyResultsTrace) SQLView.LogResult(LastInsertedId); // log the action
        return ResultedSymbols; // return the list containing this new record
    }

2

Ich habe das oben genannte versucht, aber sie haben nicht funktioniert. Ich fand diesen Gedanken, der für mich in Ordnung ist.

var ContactID = db.GetLastInsertId();

Es ist weniger Code und ich einfach einzufügen.

Hoffe das hilft jemandem.


1

Sie können SCOPE_IDENTITY auch in SQL Server aufrufen.


1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace DBDemo2
{
    public partial class Form1 : Form
    {
        string connectionString = "Database=company;Uid=sa;Pwd=mypassword";
        System.Data.SqlClient.SqlConnection connection;
        System.Data.SqlClient.SqlCommand command;

        SqlParameter idparam = new SqlParameter("@eid", SqlDbType.Int, 0);
        SqlParameter nameparam = new SqlParameter("@name", SqlDbType.NChar, 20);
        SqlParameter addrparam = new SqlParameter("@addr", SqlDbType.NChar, 10);

        public Form1()
        {
            InitializeComponent();

            connection = new System.Data.SqlClient.SqlConnection(connectionString);
            connection.Open();
            command = new System.Data.SqlClient.SqlCommand(null, connection);
            command.CommandText = "insert into employee(ename, city) values(@name, @addr);select SCOPE_IDENTITY();";

            command.Parameters.Add(nameparam);
            command.Parameters.Add(addrparam);
            command.Prepare();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {


            try
            {
                int id = Int32.Parse(textBoxID.Text);
                String name = textBoxName.Text;
                String address = textBoxAddress.Text;

                command.Parameters[0].Value = name;
                command.Parameters[1].Value = address;

                SqlDataReader reader = command.ExecuteReader();
                if (reader.HasRows)
                {
                    reader.Read();
                    int nid = Convert.ToInt32(reader[0]);
                    MessageBox.Show("ID : " + nid);
                }
                /*int af = command.ExecuteNonQuery();
                MessageBox.Show(command.Parameters["ID"].Value.ToString());
                */
            }
            catch (NullReferenceException ne)
            {
                MessageBox.Show("Error is : " + ne.StackTrace);
            }
            catch (Exception ee)
            {
                MessageBox.Show("Error is : " + ee.StackTrace);
            }
        }

        private void buttonSave_Leave(object sender, EventArgs e)
        {

        }

        private void Form1_Leave(object sender, EventArgs e)
        {
            connection.Close();
        }
    }
}

1

Es gibt viele Möglichkeiten, die zuletzt eingefügte ID abzurufen. Der einfachste Weg, den ich gefunden habe, besteht darin, sie einfach wie folgt aus dem TableAdapter im DataSet abzurufen:

<Your DataTable Class> tblData = new <Your DataTable Class>();
<Your Table Adapter Class> tblAdpt = new <Your Table Adapter Class>();

/*** Initialize and update Table Data Here ***/

/*** Make sure to call the EndEdit() method ***/
/*** of any Binding Sources before update ***/
<YourBindingSource>.EndEdit();

//Update the Dataset
tblAdpt.Update(tblData);

//Get the New ID from the Table Adapter
long newID = tblAdpt.Adapter.InsertCommand.LastInsertedId;

Hoffe das hilft ...


0

Nach dem Einfügen einer Zeile können Sie die zuletzt eingefügte ID unter der Abfragezeile abrufen.

INSERT INTO aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId); SELECT @@ IDENTITY


-1

Verwenden Sie in der Abfrage SELECT SCOPE_IDENTITY ()


-1

Danach:

INSERT INTO aspnet_GameProfiles(UserId, GameId) OUTPUT INSERTED.ID VALUES(@UserId, @GameId)

Führen Sie dies aus

int id = (int)command.ExecuteScalar;

Es wird klappen


-2

INSERT INTO aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "; dann können Sie einfach auf die letzte ID zugreifen, indem Sie die Tabelle in absteigender Reihenfolge bestellen.

SELECT TOP 1 UserId FROM aspnet_GameProfiles ORDER BY UserId DESC.


Vorausgesetzt, jemand hat IDENTITY_INSERT nicht verwendet und eine Zeile mit einer viel größeren Benutzer-ID hinzugefügt.
ldam

@Logan Ich verstehe, es kann nicht nur mit einem charv wie id oder etwas gemischtem (charv + int) funktionieren, aber Sie können eine historische Spalte mit inkrementellem int einrichten und den Trick dazu machen.
Aleks

-6
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[spCountNewLastIDAnyTableRows]
(
@PassedTableName as NVarchar(255),
@PassedColumnName as NVarchar(225)
)
AS
BEGIN
DECLARE @ActualTableName AS NVarchar(255)
DECLARE @ActualColumnName as NVarchar(225)
    SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME = @PassedTableName
    SELECT @ActualColumnName = QUOTENAME( COLUMN_NAME )
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE COLUMN_NAME = @PassedColumnName
    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = 'select MAX('+ @ActualColumnName + ') + 1  as LASTID' + ' FROM ' + @ActualTableName 
    EXEC(@SQL)
END

Dies ist, was ich wirklich nett finde ..... Jetzt können Sie die letzte inkrementierte ID aus jeder Tabelle in SQL -2005 abrufen. Dazu müssen Sie diese Prozedur nur vom Frontend aus aufrufen. Beachten Sie, dass der übergebene Spaltenname den Datentyp INT haben sollte.
Herzschlag

2
Das größte Problem dieses Ansatzes gegenüber der akzeptierten Antwort besteht darin, dass Probleme auftreten, wenn mehrere Clients gleichzeitig Daten einfügen. Wenn Client 1 zwei SQL-Aufrufe ausführt (erstens Einfügen, zweitens diese gespeicherte Prozedur) und zwischen diesen beiden Aufrufen auch ein anderer Client eine Einfügung vornimmt, erhalten Sie die falsche ID zurück!
Oliver

4
Dies gibt nicht das richtige Ergebnis zurück. Es wird der Maximalwert in der Spalte zurückgegeben (der Zeilen enthält, die andere Benutzer oder Vorgänge eingefügt haben), nicht der zuletzt von Ihnen eingefügte Wert. Daher würde dies nur auf Einzelbenutzersystemen funktionieren. Die Verwendung einer der integrierten Methoden (z. B. scope_identity ()) ist der einzig richtige Weg, um die zuletzt eingefügte ID im Kontext zu erhalten.
NickG
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.