Bagaimana cara mendapatkan id yang terakhir disisipkan?

174

Saya punya kode ini:

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

Ketika saya memasukkan ke dalam tabel ini, saya memiliki kolom kunci primer int auto_increment disebut GamesProfileId, bagaimana saya bisa mendapatkan yang terakhir dimasukkan setelah ini sehingga saya bisa menggunakan id untuk memasukkan ke dalam tabel lain?

anthonypliu
sumber

Jawaban:

256

Untuk SQL Server 2005+, jika tidak ada pemicu sisipan, maka ubah pernyataan sisipan (semua satu baris, bagi kejelasan di sini) ke ini

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

Untuk SQL Server 2000, atau jika ada pemicu penyisipan:

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

Lalu

 Int32 newId = (Int32) myCommand.ExecuteScalar();
gbn
sumber
5
OUTPUT INSERTED.IDbisa menimbulkan masalah jika ada pemicu aktif di atas meja
armen
2
Hmm. Ketika saya mencoba ini saya mendapat kesalahan: "Referensi objek tidak disetel ke instance objek." meskipun dijalankan segera setelah Jalankan.
khany
@banyakkah Anda memperbaikinya?
TuGordoBello
5
'ID' di 'OUTPUT INSERTED.ID' adalah kunci utama btw. Saya pikir itu kata yang dicadangkan.
danmbuen
1
@VoidKing: Bagaimana saya bisa mengatakan ini .. Anda melakukan sesuatu yang salah. Posting pertanyaan baru dengan kode sampel untuk bantuan. Jelas, Anda telah mengatakan kepada saya bahwa saya salah ketika itu jelas bekerja untuk semua orang kecuali Anda ...
gbn
38

Anda dapat membuat perintah dengan CommandTextsama dengan

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

dan jalankan int id = (int)command.ExecuteScalar.

Ini artikel MSDN akan memberi Anda beberapa teknik tambahan.

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

Vil ini bekerja :)

Jeba Ra
sumber
vil Saya pikir kita harus menulis jawaban yang lebih tepat secara tata bahasa agar jujur
Zizzipupp
3

Saya memiliki kebutuhan yang sama dan menemukan jawaban ini ..

Ini menciptakan catatan di tabel perusahaan (comp), itu mengambil ID otomatis yang dibuat di meja perusahaan dan menjatuhkannya ke dalam tabel Staf (staf) sehingga 2 tabel dapat dihubungkan, BANYAK staf ke SATU perusahaan. Ini berfungsi pada DB SQL 2008 saya, harus bekerja pada SQL 2005 dan di atas.

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

CREATE PROCEDURE [dbo].[InsertNewCompanyAndStaffDetails]

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

 @comp_regno nchar(8) = '12345678',

 @comp_email nvarchar(50) = '[email protected]',

 @recID INT OUTPUT

- ' @recID' digunakan untuk menyimpan nomor ID yang dibuat secara otomatis oleh Perusahaan yang akan kami ambil

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- Baris di atas digunakan untuk membuat tabel tempory untuk menampung nomor ID yang dibuat secara otomatis untuk digunakan nanti. Hanya memiliki satu bidang 'tempID' dan tipe INT -nya sama dengan '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- ' OUTPUT dimasukkan. 'Baris di atas digunakan untuk mengambil data dari bidang apa pun dalam catatan yang dibuatnya saat ini. Data yang kami inginkan adalah nomor autonumber. Jadi pastikan ia mengatakan nama bidang yang benar untuk tabel Anda, milik saya adalah 'comp_id' . Ini kemudian jatuh ke tabel tempory yang kita buat sebelumnya.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- Baris di atas digunakan untuk mencari tabel tempory yang kita buat sebelumnya di mana ID yang kita butuhkan disimpan. Karena hanya ada satu catatan di tabel tempory ini, dan hanya satu bidang, itu hanya akan memilih nomor ID yang Anda butuhkan dan memasukkannya ke ' @recID '. ' @recID ' sekarang memiliki nomor ID yang Anda inginkan dan Anda dapat menggunakannya sesuka Anda seperti saya telah menggunakannya di bawah ini.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

- Jadi begitulah. Anda benar-benar dapat mengambil apa yang Anda inginkan di baris 'OUTPUT dimasukkan. ApaEverFieldNameYouWant' dan buat bidang apa yang Anda inginkan di tabel tempory Anda dan akses untuk menggunakan apa pun yang Anda inginkan.

Saya mencari sesuatu seperti ini selama berabad-abad, dengan rincian terperinci ini, saya harap ini membantu.

Sim2K
sumber
3

Dalam SQL murni, pernyataan utama kools seperti:

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

Kurung kotak mendefinisikan simbs tabel dan kemudian kolom En dan ID, kurung bulat mendefinisikan enumerasi kolom yang akan dimulai dan kemudian nilai untuk kolom, dalam kasus saya satu kolom dan satu nilai. Apostrof melampirkan string

Saya akan menjelaskan kepada Anda pendekatan saya:

Mungkin tidak mudah untuk dipahami tetapi saya berharap berguna untuk mendapatkan gambaran besar menggunakan id yang dimasukkan terakhir. Tentu saja ada alternatif pendekatan yang lebih mudah. Tapi aku punya alasan untuk menyimpan milikku. Fungsi terkait tidak termasuk, hanya nama dan nama parameternya.

Saya menggunakan metode ini untuk kecerdasan buatan medis Metode memeriksa apakah string yang diinginkan ada di tabel pusat (1). Jika string yang diinginkan tidak ada di tabel pusat "simbs", atau jika duplikat diperbolehkan, string yang diinginkan ditambahkan ke tabel pusat "simbs" (2). Id yang diinertasi terakhir digunakan untuk membuat tabel terkait (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
sumber
2

Saya mencoba di atas tetapi mereka tidak berhasil, saya menemukan pemikiran ini, itu bekerja dengan baik untuk saya.

var ContactID = db.GetLastInsertId();

Lebih sedikit kodenya dan mudah dimasukkan.

Semoga ini bisa membantu seseorang.

Matthew Mccall
sumber
1

Anda juga dapat menggunakan panggilan ke SCOPE_IDENTITY di SQL Server.

Tim
sumber
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
sumber
1

Ada berbagai macam cara untuk mendapatkan ID yang Terakhir Dimasukkan tetapi cara termudah yang saya temukan adalah dengan hanya mengambilnya dari TableAdapter di DataSet seperti:

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

Semoga ini membantu ...

Andy Braham
sumber
0

Setelah memasukkan baris apa pun, Anda bisa mendapatkan id yang dimasukkan terakhir dengan baris permintaan di bawah ini.

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

RaviSoni-Systematix
sumber
-1

Gunakan SELECT SCOPE_IDENTITY () dalam kueri

Nimesh
sumber
-1

Sesudah ini:

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

Jalankan ini

int id = (int)command.ExecuteScalar;

Itu akan berhasil

M.Alaghemand
sumber
-2

INSERT INTO aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "; maka Anda bisa mengakses id terakhir dengan memesan tabel dengan cara desc.

PILIH TOP 1 UserId DARI aspnet_GameProfiles ORDER BY UserId DESC.

Aleks
sumber
Asalkan seseorang belum menggunakan IDENTITY_INSERT dan menambahkan baris dengan UserId yang jauh lebih besar.
ldam
@Logan saya mengerti, itu tidak bisa bekerja hanya dengan charv seperti id atau sesuatu yang dicampur (charv + int) tetapi Anda dapat mengatur kolom sejarah dengan int tambahan dan melakukan trik untuk itu.
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
DENYUT JANTUNG
sumber
Inilah yang saya pikir sangat bagus ..... Sekarang Anda bisa mendapatkan id tambahan terakhir dari tabel di SQL -2005.Untuk ini, Anda hanya perlu memanggil prosedur ini dari ujung depan. Perhatikan bahwa passColumnName harus memiliki tipe data INT.
HEARTBEAT
2
Masalah terbesar dari pendekatan ini terhadap jawaban yang diterima adalah bahwa Anda akan mengalami masalah jika beberapa klien memasukkan data secara bersamaan. Jika klien satu membuat dua panggilan sql (sisipan pertama, kedua prosedur tersimpan ini) dan di antara kedua panggilan tersebut klien lain juga membuat sisipan Anda akan mendapatkan id yang salah kembali!
Oliver
4
Ini tidak akan mengembalikan hasil yang benar. Ini akan mengembalikan nilai maksimum di kolom (yang akan memasukkan baris yang telah dimasukkan pengguna atau operasi lain) bukan nilai terakhir yang Anda masukkan. Karena itu ini hanya akan bekerja pada sistem pengguna tunggal. Menggunakan salah satu metode bawaan (misalnya scope_identity ()) adalah satu-satunya cara yang benar untuk mendapatkan ID yang dimasukkan terakhir dalam konteks.
NickG