189

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

When I insert into this table, I have an auto_increment int primary key column called GamesProfileId, how can i get the last inserted one after this so I can use that id to insert into another table?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
anthonypliu
  • 12,179
  • 28
  • 92
  • 154

16 Answers16

270

For SQL Server 2005+, if there is no insert trigger, then change the insert statement (all one line, split for clarity here) to this

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

For SQL Server 2000, or if there is an insert trigger:

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

And then

 Int32 newId = (Int32) myCommand.ExecuteScalar();
kevin cline
  • 2,608
  • 2
  • 25
  • 38
gbn
  • 422,506
  • 82
  • 585
  • 676
  • 5
    `OUTPUT INSERTED.ID` could generate problem in case of an active trigger on the table – armen Jan 22 '14 at 10:06
  • 2
    Hmm. When I tried this I got an error: "Object reference not set to an instance of an object." even though it is run immediately after the Execute. – khany May 17 '14 at 10:39
  • I'm coming from a mysql background, I can't understand this command: `Int32 newId = (Int32) myCommand.ExecuteScalar();` – Naguib Ihab May 28 '15 at 01:23
  • 5
    the 'ID' in 'OUTPUT INSERTED.ID' is the primary key btw. I thought it was a reserved word. – danmbuen Nov 25 '15 at 09:24
  • is there any MySQL version of this? – Shift 'n Tab May 23 '16 at 07:22
  • @Roel look up `LastInsertedId` for MySQL. – TylerH Sep 10 '20 at 16:10
  • @NaguibIhab With that line, you're executing the SQL query/command and also storing the return value (which is what the `Scalar` part of `ExecuteScalar` allows for) into a 32-bit Integer called `newId` so that you can use it for something later (most commonly to update another table with the ID). – TylerH Sep 11 '20 at 13:08
45

You can create a SqlCommand with CommandText equal to

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

and execute int id = (int)command.ExecuteScalar.

This MSDN article will give you some additional techniques.

TylerH
  • 20,799
  • 66
  • 75
  • 101
jason
  • 236,483
  • 35
  • 423
  • 525
7
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();
}

This will work.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Jeba Ranganathan
  • 532
  • 1
  • 8
  • 5
4

I had the same need and found this answer ..

This creates a record in the company table (comp), it the grabs the auto ID created on the company table and drops that into a Staff table (staff) so the 2 tables can be linked, MANY staff to ONE company. It works on my SQL 2008 DB, should work on SQL 2005 and above.

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

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

-- The '@recID' is used to hold the Company auto generated ID number that we are about to grab

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

-- The line above is used to create a tempory table to hold the auto generated ID number for later use. It has only one field 'tempID' and its type INT is the same as the '@recID'.

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

-- The 'OUTPUT inserted.' line above is used to grab data out of any field in the record it is creating right now. This data we want is the ID autonumber. So make sure it says the correct field name for your table, mine is 'comp_id'. This is then dropped into the tempory table we created earlier.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

-- The line above is used to search the tempory table we created earlier where the ID we need is saved. Since there is only one record in this tempory table, and only one field, it will only select the ID number you need and drop it into '@recID'. '@recID' now has the ID number you want and you can use it how you want like i have used it below.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

-- So there you go. You can actually grab what ever you want in the 'OUTPUT inserted.WhatEverFieldNameYouWant' line and create what fields you want in your tempory table and access it to use how ever you want.

I was looking for something like this for ages, with this detailed break down, I hope this helps.

Sim2K
  • 77
  • 5
3

In pure SQL the main statement kools like:

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

Square brackets defines the table simbs and then the columns En and ID, round brackets defines the enumeration of columns to be initiated and then the values for the columns, in my case one column and one value. The apostrophes enclose a string

I will explain you my approach:

It might be not easy to understand but i hope useful to get the big picture around using the last inserted id. Of course there are alternative easier approaches. But I have reasons to keep mine. Associated functions are not included, just their names and parameter names.

I use this method for medical artificial intelligence The method check if the wanted string exist in the central table (1). If the wanted string is not in the central table "simbs", or if duplicates are allowed, the wanted string is added to the central table "simbs" (2). The last inseerted id is used to create associated table (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
    }
profimedica
  • 2,716
  • 31
  • 41
2

I tried the above but they didn't work, i found this thought, that works a just fine for me.

var ContactID = db.GetLastInsertId();

Its less code and i easy to put in.

Hope this helps someone.

1

You can also use a call to SCOPE_IDENTITY in SQL Server.

Tim
  • 4,051
  • 10
  • 36
  • 60
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();
        }
    }
}
pgp
  • 89
  • 3
1

There are all sorts of ways to get the Last Inserted ID but the easiest way I have found is by simply retrieving it from the TableAdapter in the DataSet like so:

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

Hope this Helps ...

Andy Braham
  • 9,594
  • 4
  • 48
  • 56
0

After inserting any row you can get last inserted id by below line of query.

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

0

If you're using executeScalar:

cmd.ExecuteScalar();
result_id=cmd.LastInsertedId.ToString();
phoenixstudio
  • 1,776
  • 1
  • 14
  • 19
0

Maybe this answer helps as well as my database seems to have no column specified as "IDENTITY" (which is needed for "SELECT SCOPE_IDENTITY()" or "@@IDENTITY" calls). Also my "ID" column was of type "binary(16)" so I needed to convert the output like stated below:

string returnId = BitConverter.ToString((byte[])cmd.ExecuteScalar()).Replace("-", ""); 
//   skip the replace if you handle the hyphen otherwise
IVIike
  • 87
  • 8
-1

Use SELECT SCOPE_IDENTITY() in query

Nimesh
  • 3,342
  • 1
  • 28
  • 35
-1

After this:

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

Execute this

int id = (int)command.ExecuteScalar;

It will work

slfan
  • 8,950
  • 115
  • 65
  • 78
M.Alaghemand
  • 105
  • 2
  • 6
-3

INSERT INTO aspnet_GameProfiles(UserId,GameId) VALUES(@UserId, @GameId)"; then you can just access to the last id by ordering the table in desc way.

SELECT TOP 1 UserId FROM aspnet_GameProfiles ORDER BY UserId DESC.

Aleks
  • 19
  • 4
  • Provided someone hasn't used IDENTITY_INSERT and added a row with a much larger UserId. – ldam Sep 25 '18 at 11:18
  • @Logan i understand, its can't work with just a charv like id or something mixed (charv+int) but you can set up a historical column with incremental int and do the trick on that. – Aleks Oct 25 '18 at 09:26
-8
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
Oliver
  • 43,366
  • 8
  • 94
  • 151
HEARTBEAT
  • 39
  • 2
  • 11
  • This is what i think is really nice..... Now you can get the last incremented id from any of the table in SQL -2005.For this you only need to call this procedure from front end. Notice that the passedColumnName should have the data type INT. – HEARTBEAT May 15 '12 at 07:05
  • 3
    The biggest problem of this approach against the accepted answer is that you'll run into problems if multiple clients are inserted data at the same time. If client one makes two sql calls (first insert, second this stored procedure) and between those two calls another client also makes an insert you'll get the wrong id back! – Oliver May 15 '12 at 07:27
  • 6
    This will not return the correct result. It will return the maximum value in the column (which will include rows other users or operations have inserted) not the last value YOU inserted. Therefore this would only work on single user systems. Using one of the built in methods (eg scope_identity() ) is the only correct way to get the last inserted ID within the context. – NickG May 29 '13 at 14:28