Come ottenere l'ultimo ID inserito?


174

Ho questo codice:

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();
}

Quando inserisco in questa tabella, ho chiamato una colonna chiave primaria auto_increment int GamesProfileId , come posso ottenere l'ultima inserita dopo questa in modo da poter usare quell'id per inserire in un'altra tabella?

Risposte:


256

Per SQL Server 2005+, se non è presente alcun trigger di inserimento, modificare l'istruzione insert (tutta una riga, divisa per chiarezza qui) in questo

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

Per SQL Server 2000 o se è presente un trigger di inserimento:

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

E poi

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

5
OUTPUT INSERTED.IDpotrebbe generare problemi in caso di attivazione attiva sul tavolo
armen

2
Hmm. Quando ho provato questo ho ricevuto un errore: "Riferimento oggetto non impostato su un'istanza di un oggetto". anche se viene eseguito immediatamente dopo Execute.
khany,

@khany l'hai risolto?
TuGordoBello,

5
l '"ID" in "OUTPUT INSERTED.ID" è la chiave primaria tra. Ho pensato che fosse una parola riservata.
danmbuen,

1
@VoidKing: Come posso dirlo .. stai facendo qualcosa di sbagliato. Pubblica una nuova domanda con un codice di esempio per assistenza. Ovviamente, mi hai detto che ho torto quando funziona chiaramente per tutti tranne te ...
gbn

38

È possibile creare un comando CommandTextuguale a

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

ed eseguire int id = (int)command.ExecuteScalar .

Questo articolo MSDN ti fornirà alcune tecniche aggiuntive.


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();
}

Questo vil funziona :)


vil? Penso che dovremmo scrivere risposte grammaticalmente più corrette per essere onesti
Zizzipupp,

3

Ho avuto lo stesso bisogno e ho trovato questa risposta ..

Questo crea un record nella tabella dell'azienda (comp), prende l'ID automatico creato nella tabella dell'azienda e lo rilascia in una tabella Staff (personale) in modo che le 2 tabelle possano essere collegate, MOLTI membri del personale a UNA società. Funziona sul mio DB SQL 2008, dovrebbe funzionare su SQL 2005 e versioni successive.

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

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

- " @recID" viene utilizzato per contenere il numero ID generato automaticamente dalla società che stiamo per acquisire

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- La riga sopra è utilizzata per creare una tabella dei tempi per contenere il numero ID generato automaticamente per un uso successivo. Ha solo un campo 'tempID' e il suo tipo INT è lo stesso di '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- L' USCITA inserita. 'la riga sopra viene utilizzata per estrarre i dati da qualsiasi campo nel record che sta creando in questo momento. Questo dato che vogliamo è il numero di identificazione automatico. In modo da assicurarsi che dice il nome di campo corretto per la vostra tavola, il mio è 'COMP_ID' . Questo viene quindi rilasciato nella tabella dei tempi creata in precedenza.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- La riga sopra viene utilizzata per cercare la tabella dei tempi creata in precedenza in cui viene salvato l'ID di cui abbiamo bisogno. Poiché in questa tabella temporale è presente un solo record e un solo campo, selezionerà solo il numero ID necessario e lo trascinerà in " @recID ". ' @recID ' ora ha il numero ID che desideri e puoi usarlo come vuoi come l'ho usato qui sotto.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

- Quindi eccoti. Puoi effettivamente prendere ciò che vuoi in "OUTPUT inserito.WhatEverFieldNameYouWant" riga e creare quali campi vuoi nella tua tabella dei tempi e accedervi per usare come vuoi.

Stavo cercando qualcosa del genere da anni, con questa suddivisione dettagliata, spero che questo aiuti.


3

In puro SQL l'istruzione principale kools come:

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

Le parentesi quadre definiscono i simbi della tabella e quindi le colonne En e ID, le parentesi tonde definiscono l'enumerazione delle colonne da avviare e quindi i valori per le colonne, nel mio caso una colonna e un valore. Gli apostrofi racchiudono una stringa

Ti spiego il mio approccio:

Potrebbe non essere facile da capire, ma spero utile avere una visione d'insieme usando l'ultimo ID inserito. Naturalmente ci sono approcci alternativi più semplici. Ma ho motivi per mantenere il mio. Le funzioni associate non sono incluse, ma solo i loro nomi e nomi dei parametri.

Uso questo metodo per l'intelligenza artificiale medica. Il metodo controlla se la stringa desiderata esiste nella tabella centrale (1). Se la stringa desiderata non si trova nella tabella centrale "simbs", o se sono consentiti duplicati, la stringa desiderata viene aggiunta alla tabella centrale "simbs" (2). L'ultimo ID inserito viene utilizzato per creare la tabella associata (3).

    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

Ho provato quanto sopra ma non hanno funzionato, ho trovato questo pensiero, che funziona bene per me.

var ContactID = db.GetLastInsertId();

È meno codice e sono facile da inserire.

Spero che questo aiuti qualcuno.


1

È inoltre possibile utilizzare una chiamata a SCOPE_IDENTITY in SQL Server.


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

Esistono molti modi per ottenere l'ultimo ID inserito, ma il modo più semplice che ho trovato è semplicemente recuperandolo dal TableAdapter nel DataSet in questo modo:

<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;

Spero che questo ti aiuti ...


0

Dopo aver inserito una riga è possibile ottenere l'ultimo ID inserito dalla riga di query sottostante.

INSERISCI IN aspnet_GameProfiles (UserId, GameId) VALORI (@UserId, @GameId); SELEZIONA @@ IDENTITÀ


-1

Utilizzare SELECT SCOPE_IDENTITY () nella query


-1

Dopodichè:

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

Esegui questo

int id = (int)command.ExecuteScalar;

Funzionerà


-2

INSERISCI IN aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "; quindi puoi semplicemente accedere all'ultimo ID ordinando la tabella in modo discendente.

SELEZIONA TOP 1 UserId DA aspnet_GameProfiles ORDINA PER UserId DESC.


A condizione che qualcuno non abbia usato IDENTITY_INSERT e abbia aggiunto una riga con un ID utente molto più grande.
ldam,

@Logan ho capito, non può funzionare solo con un charv come id o qualcosa di misto (charv + int) ma puoi impostare una colonna storica con int incrementale e fare il trucco su questo.
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

Questo è quello che penso sia davvero bello ..... Ora puoi ottenere l'ultimo ID incrementato da qualsiasi tabella in SQL -2005.Per questo devi solo chiamare questa procedura dal front-end. Si noti che passatoColumnName deve avere il tipo di dati INT.
HEARTBEAT,

2
Il problema più grande di questo approccio rispetto alla risposta accettata è che si verificano problemi se più client vengono inseriti contemporaneamente dati. Se il client uno effettua due chiamate sql (primo inserimento, secondo questa procedura memorizzata) e tra queste due chiamate anche un altro client effettua un inserimento, ti verrà restituito l'ID sbagliato!
Oliver,

4
Questo non restituirà il risultato corretto. Restituirà il valore massimo nella colonna (che includerà le righe inserite da altri utenti o operazioni) non l'ultimo valore inserito. Pertanto, ciò funzionerebbe solo su sistemi a utente singolo. L'uso di uno dei metodi integrati (ad esempio scope_identity ()) è l'unico modo corretto per ottenere l'ultimo ID inserito nel contesto.
NickG,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.