Son eklenen kimlik nasıl alınır?


174

Bu kod var:

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

Bu tabloya eklediğimde, bir auto_increment int birincil anahtar sütunu var GamesProfileId, başka bir tabloya eklemek için bu kimliği kullanabilmek için bundan sonra son eklenen birini nasıl alabilirim?

Yanıtlar:


256

SQL Server 2005+ için, ekleme tetikleyicisi yoksa, ekleme deyimini (burada netlik için bölünmüş tek satır) bunu değiştirin

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

SQL Server 2000 için veya bir ekleme tetikleyicisi varsa:

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

Ve sonra

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

5
OUTPUT INSERTED.IDMasada aktif bir tetikleyici olması durumunda sorun yaratabilir
armen

2
Hmm. Bunu denediğimde bir hata aldım: "Nesne başvurusu bir nesnenin örneğine ayarlanmadı." Yürütme işleminden hemen sonra çalıştırılsa bile.
khany

@khany tamir ettin mi?
TuGordoBello

5
'OUTPUT INSERTED.ID' içindeki 'ID' birincil anahtar btw'dir. Ayrılmış bir kelime olduğunu düşündüm.
danmbuen

1
@VoidKing: Bunu nasıl koyabilirim .. yanlış bir şey yapıyorsun. Yardım için örnek kodla yeni bir soru gönderin. Açıkçası, senden başka herkes için açıkça işe yaradığında yanlış olduğumu söyledin ...
gbn

38

CommandTextŞuna eşit bir komut oluşturabilirsiniz:

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

ve çalıştırın int id = (int)command.ExecuteScalar.

Bu MSDN makalesi size bazı ek teknikler verecektir.


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

Bu kötü çalışma :)


vil? Dürüst olmak gerekirse dilbilgisi açısından daha doğru cevaplar yazmamız gerektiğini düşünüyorum
Zizzipupp

3

Aynı ihtiyacı vardı ve bu cevabı buldum ..

Bu, şirket tablosunda (comp) bir kayıt oluşturur, şirket tablosunda oluşturulan otomatik kimliği yakalar ve bunu bir Personel tablosuna (personel) bırakır, böylece 2 tablo, BİR şirkete ÇOK personel bağlanabilir. SQL 2005 DB üzerinde çalışır, SQL 2005 ve üstü üzerinde çalışmalıdır.

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

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' , kapmak üzere olduğumuz Şirket tarafından otomatik olarak oluşturulan kimlik numarasını tutmak için kullanılır

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- Yukarıdaki satır, daha sonra kullanmak üzere otomatik olarak oluşturulan kimlik numarasını tutmak için geçici bir tablo oluşturmak için kullanılır. Bu yalnızca bir alan 'tempID' vardır ve tipi INT aynıdır '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- ' ÇIKIŞ takıldı. 'satırı yukarıdaki verileri şu anda oluşturduğu kayıttaki herhangi bir alandan almak için kullanılır. İstediğimiz bu veri kimlik otomatik numarasıdır. Bu yüzden tablonuz için doğru alan adını söylediğinden emin olun, benimki 'comp_id' . Bu daha sonra daha önce yarattığımız geçici tabloya düşüyor.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- Yukarıdaki satır, ihtiyacımız olan kimliğin kaydedildiği, daha önce oluşturduğumuz geçici tabloyu aramak için kullanılır. Bu geçici tabloda yalnızca bir kayıt ve yalnızca bir alan olduğundan, yalnızca ihtiyacınız olan kimlik numarasını seçecek ve ' @recID ' içine bırakacaktır . ' @recID ' artık istediğiniz kimlik numarasına sahiptir ve aşağıda nasıl kullandığımı istediğiniz gibi kullanabilirsiniz.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

-- Al işte ozaman, buyur. Aslında 'OUTPUT eklenmiş.WhatEverFieldNameYouWant' satırında istediğinizi alabilir ve tempory tablonuzda istediğiniz alanları oluşturabilir ve istediğiniz şekilde kullanmak için ona erişebilirsiniz.

Çağlar boyunca böyle bir şey arıyordum, bu ayrıntılı yıkımla, umarım bu yardımcı olur.


3

Saf SQL'de ana ifade kools gibi:

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

Köşeli parantezler tablo simbs'i ve sonra En ve ID sütunlarını, yuvarlak parantezler başlatılacak sütunların numaralandırılmasını ve sonra da benim durumumda bir sütun ve bir değer olmak üzere sütunların değerlerini tanımlar. Kesme işaretleri bir dizeyi kapsar

Size yaklaşımımı açıklayacağım:

Anlamak kolay olmayabilir, ancak son eklenen kimliği kullanarak etraftaki büyük resmi almak için yararlı olacağını umuyorum. Tabii ki alternatif daha kolay yaklaşımlar var. Ama benimkini tutmak için nedenlerim var. İlişkili işlevler dahil edilmez, yalnızca adları ve parametre adları dahil edilir.

Tıbbi yapay zeka için bu yöntemi kullanıyorum Yöntem, istenen dizginin orta tabloda (1) var olup olmadığını kontrol eder. İstenen dize "simbs" orta tablosunda değilse veya kopyalara izin veriliyorsa, istenen dize "simbs" orta tablosuna eklenir (2). Son içe aktarılan kimlik, ilişkili tablo (3) oluşturmak için kullanılır.

    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

Yukarıdakileri denedim ama işe yaramadı, bu düşünceyi buldum, bu benim için iyi çalışıyor.

var ContactID = db.GetLastInsertId();

Onun daha az kod ve ben koymak kolay.

Umarım bu birine yardımcı olur.


1

SQL Server'da SCOPE_IDENTITY çağrısını da kullanabilirsiniz.


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

Son Eklenen Kimliği almanın her türlü yolu vardır, ancak bulduğum en kolay yol, bunu DataSet'teki TableAdapter'ten alarak elde etmektir:

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

Bu yardımcı olur umarım ...


0

Herhangi bir satırı ekledikten sonra, sorgu satırının altındaki son eklenen kimliği alabilirsiniz.

Aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId); @@ KİMLİĞİ SEÇ



-1

Bundan sonra:

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

Bunu yürütün

int id = (int)command.ExecuteScalar;

Çalışacak


-2

Aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "içine girin; sonra tabloyu aynı şekilde sıralayarak son kimliğe erişebilirsiniz.

ÜST 1 kullanıcı kimliği aspnet_GameProfiles ORDER BY UserId DESC.


Birisi IDENTITY_INSERT kullanmamışsa ve çok daha büyük bir UserId içeren bir satır eklemişse.
ldam

@ Anlıyorum, sadece id veya karışık bir şey (charv + int) gibi bir charv ile çalışamaz, ancak artımlı int ile tarihsel bir sütun oluşturabilir ve bu konuda hile yapabilirsiniz.
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

Bu gerçekten güzel olduğunu düşünüyorum ..... Şimdi SQL -2005 tablosunun herhangi birinden son artan kimliği alabilirsiniz.Bu amaçla sadece ön uç bu yordamı çağırmanız gerekir. PassColumnName, veri türü INT olmalıdır dikkat edin.
KALP ATIŞI

2
Bu yaklaşımın kabul edilen yanıta karşı en büyük sorunu, aynı anda birden fazla istemci veri eklenirse sorun yaşamanızdır. İstemci biri iki sql çağrı yaparsa (ilk ekleme, ikinci bu saklı yordam) ve bu iki çağrı arasında başka bir istemci de bir ekleme yapar yanlış kimliği geri alırsınız!
Oliver

4
Bu doğru sonucu döndürmez. En son girdiğiniz değeri değil, sütundaki maksimum değeri döndürür (diğer kullanıcıların veya işlemlerin eklediği satırları içerir). Bu nedenle bu yalnızca tek kullanıcılı sistemlerde çalışır. Bağlam içinde son eklenen kimliği almanın tek doğru yolu yerleşik yöntemlerden birini kullanmaktır (ör. Scope_identity ()).
NickG
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.