Làm thế nào để có được id cuối cùng được chèn?


174

Tôi có mã này:

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

Khi tôi chèn vào bảng này, tôi có một cột khóa chính int_increment int được gọi GamesProfileId, làm thế nào tôi có thể chèn cái cuối cùng sau cái này để tôi có thể sử dụng id đó để chèn vào bảng khác?

Câu trả lời:


256

Đối với SQL Server 2005+, nếu không có trình kích hoạt chèn, thì hãy thay đổi câu lệnh chèn (tất cả một dòng, phân tách cho rõ ràng ở đây) thành điều này

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

Đối với SQL Server 2000 hoặc nếu có trình kích hoạt chèn:

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

Và sau đó

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

5
OUTPUT INSERTED.IDcó thể phát sinh sự cố trong trường hợp kích hoạt hoạt động trên bàn
armen

2
Hừm. Khi tôi thử điều này, tôi đã gặp một lỗi: "Tham chiếu đối tượng không được đặt thành phiên bản của đối tượng." mặc dù nó được chạy ngay sau khi thực thi.
khany

@khany bạn đã sửa chưa?
TuGordoBello

5
'ID' trong 'OUTPUT INSERTED.ID' là khóa chính btw. Tôi nghĩ đó là một từ dành riêng.
danmbuen

1
@VoidKing: Làm thế nào tôi có thể đặt cái này .. bạn đang làm gì đó sai. Gửi một câu hỏi mới với mã mẫu để được giúp đỡ. Rõ ràng, bạn đã nói với tôi rằng tôi đã sai khi nó hoạt động tốt cho tất cả mọi người trừ bạn ...
gbn

38

Bạn có thể tạo một lệnh CommandTextbằng

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

và thực hiện int id = (int)command.ExecuteScalar.

Bài viết MSDN này sẽ cung cấp cho bạn một số kỹ thuật bổ sung.


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 này làm việc :)


vil? Tôi nghĩ rằng chúng ta nên viết các câu trả lời đúng ngữ pháp hơn để trung thực
Zizzipupp

3

Tôi có cùng nhu cầu và tìm thấy câu trả lời này ..

Điều này tạo ra một bản ghi trong bảng công ty (comp), nó lấy ID tự động được tạo trên bảng công ty và thả nó vào bảng Nhân viên (nhân viên) để có thể liên kết 2 bảng, NHIỀU nhân viên cho MỘT công ty. Nó hoạt động trên SQL 2008 DB của tôi, nên hoạt động trên SQL 2005 trở lên.

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

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' được sử dụng để giữ số ID được tạo tự động của Công ty mà chúng tôi sắp lấy

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- Dòng trên được sử dụng để tạo bảng tempory để giữ số ID được tạo tự động để sử dụng sau. Nó chỉ có một trường 'tempID' và kiểu INT của nó giống như '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- ' ĐẦU RA được chèn. 'dòng trên được sử dụng để lấy dữ liệu từ bất kỳ trường nào trong bản ghi mà nó đang tạo ngay bây giờ. Dữ liệu này chúng tôi muốn là số tự động ID. Vì vậy, hãy chắc chắn rằng nó nói tên trường chính xác cho bảng của bạn, của tôi là 'comp_id' . Điều này sau đó được thả vào bảng tempory chúng tôi tạo ra trước đó.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- Dòng trên được sử dụng để tìm kiếm bảng tempory mà chúng ta đã tạo trước đó trong đó ID chúng ta cần được lưu. Vì chỉ có một bản ghi trong bảng tạm thời này và chỉ có một trường, nên nó sẽ chỉ chọn số ID bạn cần và thả nó vào ' @recID '. ' @recID ' hiện có số ID bạn muốn và bạn có thể sử dụng số đó theo cách bạn muốn như tôi đã sử dụng dưới đây.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

- Vậy em đi đây. Bạn thực sự có thể lấy những gì bạn muốn trong dòng 'OUTPUT được chèn.WhatEverFieldNameYouWant' và tạo những trường bạn muốn trong bảng tempory của bạn và truy cập nó để sử dụng bao giờ bạn muốn.

Tôi đã tìm kiếm một cái gì đó như thế này từ lâu, với sự cố chi tiết này, tôi hy vọng điều này sẽ giúp ích.


3

Trong SQL thuần, câu lệnh chính kools như:

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

Dấu ngoặc vuông xác định các simbs của bảng và sau đó là cột En và ID, dấu ngoặc tròn xác định kiểu liệt kê của các cột sẽ được bắt đầu và sau đó là các giá trị cho các cột, trong trường hợp của tôi là một cột và một giá trị. Các dấu nháy đơn bao gồm một chuỗi

Tôi sẽ giải thích cho bạn cách tiếp cận của tôi:

Nó có thể không dễ hiểu nhưng tôi hy vọng sẽ hữu ích để có được bức tranh lớn xung quanh bằng cách sử dụng id được chèn cuối cùng. Tất nhiên có những cách tiếp cận dễ dàng hơn. Nhưng tôi có lý do để giữ của tôi. Các hàm liên kết không được bao gồm, chỉ có tên và tên tham số của chúng.

Tôi sử dụng phương pháp này cho trí tuệ nhân tạo y tế Phương pháp kiểm tra xem chuỗi mong muốn có tồn tại trong bảng trung tâm không (1). Nếu chuỗi mong muốn không nằm trong bảng trung tâm "simbs" hoặc nếu cho phép trùng lặp, chuỗi mong muốn sẽ được thêm vào bảng trung tâm "simbs" (2). Id inseerted cuối cùng được sử dụng để tạo bảng liên kết (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

Tôi đã thử ở trên nhưng chúng không hoạt động, tôi thấy suy nghĩ này, nó hoạt động tốt với tôi.

var ContactID = db.GetLastInsertId();

Nó ít mã hơn và tôi dễ dàng để đưa vào.

Hy vọng điều này sẽ giúp được ai đó.


1

Bạn cũng có thể sử dụng lệnh gọi tới SCOPE_IDENTITY trong 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

Có tất cả các cách để lấy ID được chèn lần cuối nhưng cách dễ nhất tôi đã tìm thấy chỉ bằng cách truy xuất nó từ TableAd CHƯƠNG trong Bộ dữ liệu như vậy:

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

Hi vọng điêu nay co ich ...


0

Sau khi chèn bất kỳ hàng nào, bạn có thể nhận id được chèn cuối cùng bằng dòng truy vấn bên dưới.

XÁC NHẬN VÀO aspnet_GameProfiles (UserId, GameId) GIÁ TRỊ (@UserId, @GameId); CHỌN @@ SẮC


-1

Sử dụng CHỌN SCOPE_IDENTITY () trong truy vấn


-1

Sau đây:

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

Thực hiện điều này

int id = (int)command.ExecuteScalar;

Nó sẽ làm việc


-2

XÁC NHẬN VÀO aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "; sau đó bạn chỉ có thể truy cập vào id cuối cùng bằng cách đặt hàng bảng theo cách desc.

CHỌN TOP 1 UserId TỪ aspnet_GameProfiles ĐẶT HÀNG THEO UserId DESC.


Với điều kiện ai đó chưa sử dụng IDENTITY_INSERT và đã thêm một hàng với UserId lớn hơn nhiều.
ldam

@Logan tôi hiểu, nó không thể hoạt động chỉ với một charv như id hoặc một cái gì đó hỗn hợp (charv + int) nhưng bạn có thể thiết lập một cột lịch sử với int tăng dần và thực hiện thủ thuật đó.
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

Đây là những gì tôi nghĩ là thực sự tốt đẹp ..... Bây giờ bạn có thể nhận được id tăng cuối cùng từ bất kỳ bảng nào trong SQL -2005. Đối với điều này, bạn chỉ cần gọi thủ tục này từ giao diện người dùng. Lưu ý rằng PassColumnName phải có kiểu dữ liệu INT.
TRÁI TIM

2
Vấn đề lớn nhất của phương pháp này đối với câu trả lời được chấp nhận là bạn sẽ gặp vấn đề nếu nhiều khách hàng được chèn dữ liệu cùng một lúc. Nếu khách hàng thực hiện hai cuộc gọi sql (lần chèn đầu tiên, lần thứ hai thủ tục được lưu trữ này) và giữa hai cuộc gọi đó, khách hàng khác cũng thực hiện thao tác chèn, bạn sẽ nhận lại id sai!
Oliver

4
Điều này sẽ không trả lại kết quả chính xác. Nó sẽ trả về giá trị tối đa trong cột (sẽ bao gồm các hàng mà người dùng hoặc hoạt động khác đã chèn) không phải là giá trị cuối cùng BẠN đã chèn. Do đó, điều này sẽ chỉ hoạt động trên các hệ thống người dùng duy nhất. Sử dụng một trong các phương thức dựng sẵn (ví dụ scope_identity ()) là cách chính xác duy nhất để có được ID được chèn cuối cùng trong ngữ cảnh.
NickG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.