마지막으로 삽입 된 아이디를 얻는 방법?


174

이 코드가 있습니다 :

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

이 테이블에 삽입 할 때 auto_increment int 기본 키 열 GamesProfileId이 있습니다.이 ID를 사용하여 다른 테이블에 삽입 할 수 있도록 마지막에 삽입 된 열을 어떻게 얻을 수 있습니까?

답변:


256

SQL Server 2005+의 경우 삽입 트리거가없는 경우 삽입 명령문 (모두 한 줄씩, 여기에서는 명확성을 위해 분할)을 다음과 같이 변경하십시오.

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

SQL Server 2000의 경우 또는 삽입 트리거가있는 경우 :

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

그리고

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

5
OUTPUT INSERTED.ID테이블에서 활성 트리거의 경우 문제를 일으킬 수 있음
armen

2
흠. 이것을 시도했을 때 "객체 참조가 객체의 인스턴스로 설정되지 않았습니다"라는 오류가 발생했습니다. 실행 직후에 실행 되더라도.
khany

@khany 고쳤습니까?
TuGordoBello

5
'OUTPUT INSERTED.ID'의 'ID'는 기본 키 btw입니다. 나는 그것이 예약어라고 생각했다.
danmbuen

1
@VoidKing : 이걸 어떻게 넣을 수 있을까요. 당신은 뭔가 잘못하고 있습니다. 도움을 받으려면 샘플 코드로 새 질문을 게시하십시오. 분명히, 당신은 내가 당신을 제외한 모든 사람들에게 분명히 효과가있을 때 내가 틀렸다고 말했습니다.
gbn

38

다음과 CommandText같은 명령을 만들 수 있습니다

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

실행하십시오 int id = (int)command.ExecuteScalar.

MSDN 기사에서는 몇 가지 추가 기술을 제공합니다.


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

이 악한 일 :)


악? 솔직히 말해서 더 문법적으로 정확한 답을 써야한다고 생각합니다.
Zizzipupp

3

나는 똑같은 필요가 있었고이 대답을 찾았습니다 ..

이렇게하면 회사 테이블 (comp)에 레코드가 작성되고 회사 테이블에서 작성된 자동 ID를 가져 와서 직원 테이블 (스태프)에 놓아 두 테이블을 연결할 수 있으므로 많은 직원이 한 회사에 연결됩니다. 내 SQL 2008 DB에서 작동하며 SQL 2005 이상에서 작동해야합니다.

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

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' 는 회사에서 자동 생성하려는 ID 번호를 보유하는 데 사용됩니다.

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

-위의 줄은 나중에 사용하기 위해 자동 생성 된 ID 번호를 보유 할 임시 테이블을 만드는 데 사용됩니다. 그것은 단지 하나의 필드 'TEMPID'을 가지고 있으며, 그 유형 INT는 과 동일 '@recID' .

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- ' OUTPUT이 삽입되었습니다. '위의 행은 현재 작성중인 레코드의 필드에서 데이터를 가져 오는 데 사용됩니다. 우리가 원하는이 데이터는 ID 자동 번호입니다. 따라서 테이블의 올바른 필드 이름이 'comp_id' 인지 확인하십시오 . 그런 다음 이전에 만든 임시 테이블로 삭제됩니다.

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

-위의 줄은 필요한 ID가 저장되어있는 이전에 만든 임시 테이블을 검색하는 데 사용됩니다. 이 임시 테이블에는 하나의 레코드 만 있고 하나의 필드 만 있기 때문에 필요한 ID 번호 만 선택하여 ' @recID '에 드롭합니다 . ' @recID '에는 원하는 ID 번호가 있으며 아래에서 사용한 것처럼 원하는 방식으로 사용할 수 있습니다.

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

-그렇습니다. 실제로 'OUTPUT insert.WhatEverFieldNameYouWant' 줄 에서 원하는 것을 잡고 임시 테이블에서 원하는 필드를 만들고 원하는 방식으로 액세스 할 수 있습니다.

나는 세세한 세분화와 함께 오랜 세월 동안 이와 같은 것을 찾고 있었는데 이것이 도움이되기를 바랍니다.


3

순수한 SQL에서 주요 문장은 다음과 같습니다.

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

대괄호는 테이블 단순을 정의한 다음 열 En 및 ID를 정의하고, 대괄호는 시작할 열의 열거를 정의한 다음 열 값 (내 경우에는 하나의 열과 하나의 값)을 정의합니다. 아포스트로피는 문자열을 묶습니다.

나는 당신에게 나의 접근법을 설명 할 것이다 :

이해하기 쉽지 않을 수도 있지만 마지막으로 삽입 된 ID를 사용하여 큰 그림을 얻는 것이 유용하기를 바랍니다. 물론 더 쉬운 대안이 있습니다. 그러나 나는 내 것을 유지해야 할 이유가 있습니다. 관련 함수는 이름 및 매개 변수 이름 만 포함됩니다.

의료 인공 지능에이 방법을 사용합니다. 방법이 원하는 문자열이 중앙 테이블에 있는지 확인합니다 (1). 원하는 문자열이 중앙 테이블 "simbs"에 없거나 중복이 허용되는 경우 원하는 문자열이 중앙 테이블 "simbs"(2)에 추가됩니다. 마지막으로 삽입 된 ID는 관련 테이블 (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

나는 위를 시도했지만 작동하지 않았다. 나는이 생각을 발견했다.

var ContactID = db.GetLastInsertId();

코드가 적고 넣기가 쉽습니다.

이것이 누군가를 돕기를 바랍니다.


1

SQL Server에서 SCOPE_IDENTITY에 대한 호출을 사용할 수도 있습니다.


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

마지막으로 삽입 된 ID를 얻는 모든 종류의 방법이 있지만 내가 찾은 가장 쉬운 방법은 DataSet의 TableAdapter에서 간단히 다음과 같이 검색하는 것입니다.

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

도움이 되었기를 바랍니다 ...


0

행을 삽입 한 후 아래 줄의 쿼리로 마지막으로 삽입 된 ID를 얻을 수 있습니다.

aspnet_GameProfiles (UserId, GameId)에 삽입 VALUES (@UserId, @GameId); @@ IDENTITY 선택



-1

금후:

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

이것을 실행

int id = (int)command.ExecuteScalar;

작동합니다


-2

INSERT INTO aspnet_GameProfiles (UserId, GameId) VALUES (@UserId, @GameId) "; 그러면 테이블을 desc 방식으로 정렬하여 마지막 id에 액세스 할 수 있습니다.

aspnet_GameProfiles에서 상위 1 개의 UserId를 선택하십시오.


누군가가 IDENTITY_INSERT를 사용하지 않고 훨씬 더 큰 UserId를 가진 행을 추가 한 경우.
ldam

@ Logan 이해합니다 .ID와 같은 charv 또는 혼합 된 문자 (charv + int)로는 작동 할 수 없지만 incremental int로 기록 열을 설정하고 그에 대한 트릭을 수행 할 수 있습니다.
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

이것이 내가 정말로 훌륭하다고 생각하는 것입니다 ..... 이제 SQL -2005의 테이블에서 마지막으로 증가 된 ID를 얻을 수 있습니다. passedColumnName의 데이터 유형은 INT 여야합니다.
HEARTBEAT

2
허용 된 답변에 대한이 방법의 가장 큰 문제는 여러 클라이언트가 동시에 데이터를 삽입하면 문제가 발생할 수 있다는 것입니다. 클라이언트 1이 두 번의 SQL 호출 (첫 번째 삽입, 두 번째이 저장 프로 시저)을 수행하고 해당 두 호출 사이에 다른 클라이언트가 삽입을하면 잘못된 ID를 다시 얻습니다!
Oliver

4
올바른 결과를 반환하지 않습니다. 마지막으로 삽입 한 값이 아닌 다른 사용자 나 작업이 삽입 한 행을 포함하여 열의 최대 값을 반환합니다. 따라서 이것은 단일 사용자 시스템에서만 작동합니다. 내장 된 메소드 중 하나 (예 : scope_identity ())를 사용하는 것이 컨텍스트 내에서 마지막으로 삽입 된 ID를 얻는 유일한 올바른 방법입니다.
NickG
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.