วิธีรับรหัสที่ใส่ครั้งสุดท้าย


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ว่าฉันจะแทรกสุดท้ายได้อย่างไรหลังจากนี้ฉันจึงสามารถใช้รหัสนั้นเพื่อแทรกเข้าไปในตารางอื่นได้หรือไม่

คำตอบ:


256

สำหรับ SQL Server 2005+ หากไม่มีทริกเกอร์การแทรกให้เปลี่ยนคำสั่ง insert (ทั้งหมดหนึ่งบรรทัดแยกเพื่อความชัดเจนที่นี่)

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
อืมมม เมื่อฉันลองทำสิ่งนี้ฉันพบข้อผิดพลาด: "การอ้างอิงวัตถุไม่ได้ถูกตั้งค่าเป็นอินสแตนซ์ของวัตถุ" แม้ว่าจะถูกเรียกใช้ทันทีหลังจากดำเนินการ
kanyany

@ KHany คุณแก้ไขหรือไม่
TuGordoBello

5
'ID' ใน 'OUTPUT INSERTED.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();
}

vil นี้ใช้งานได้ :)


Vil? ฉันคิดว่าเราควรเขียนคำตอบที่ถูกต้องตามหลักไวยากรณ์มากขึ้นเพื่อความซื่อสัตย์
Zizzipupp

3

ฉันมีความต้องการเดียวกันและพบคำตอบนี้ ..

สิ่งนี้จะสร้างเร็กคอร์ดในตาราง บริษัท (คอมพ์) มันจะคว้า auto ID ที่สร้างขึ้นในตาราง บริษัท และวางลงในตารางพนักงาน (พนักงาน) เพื่อให้สามารถเชื่อมโยงตาราง 2 ตารางพนักงานหลายคนกับหนึ่ง บริษัท มันใช้งานได้กับ 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'ใช้เพื่อเก็บหมายเลขประจำตัวที่สร้างขึ้นโดยอัตโนมัติของ บริษัท ที่เรากำลังจะคว้า

AS
 Begin

  SET NOCOUNT ON

  DECLARE @tableVar TABLE (tempID INT)

- บรรทัดด้านบนใช้สำหรับสร้างตาราง tempory เพื่อเก็บหมายเลข ID ที่สร้างขึ้นอัตโนมัติเพื่อใช้ในภายหลัง มันจะมีเพียงหนึ่งฟิลด์ 'tempID และประเภทของINTเป็นเช่นเดียวกับ'@recID'

  INSERT INTO comp(comp_name, comp_regno, comp_email) 

  OUTPUT inserted.comp_id INTO @tableVar

- ใส่ 'เอาท์พุท ' 'บรรทัดด้านบนใช้เพื่อดึงข้อมูลออกจากเขตข้อมูลใด ๆ ในระเบียนที่สร้างขึ้นในขณะนี้ ข้อมูลนี้เราต้องการคือหมายเลขประจำตัวประชาชน เพื่อให้แน่ใจว่ามันบอกว่าชื่อฟิลด์ที่ถูกต้องสำหรับตารางของคุณฉันเป็น'comp_id' สิ่งนี้จะถูกดร็อปลงในตาราง tempory ที่เราสร้างไว้ก่อนหน้านี้

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)

- บรรทัดด้านบนใช้เพื่อค้นหาตาราง tempory ที่เราสร้างขึ้นก่อนหน้านี้ซึ่ง ID ที่เราต้องการจะถูกบันทึกไว้ เนื่องจากมีเพียงหนึ่งระเบียนในตาราง tempory นี้และมีเพียงหนึ่งฟิลด์เท่านั้นจึงจะเลือกหมายเลข ID ที่คุณต้องการและวางลงใน ' @recID ' ' @recID ' ตอนนี้มีหมายเลข ID ที่คุณต้องการและคุณสามารถใช้วิธีที่คุณต้องการเช่นฉันได้ใช้มันด้านล่าง

  INSERT INTO staff(Staff_comp_id) 
  VALUES (@recID)

 End

- แล้วคุณไป คุณสามารถคว้าสิ่งที่คุณต้องการได้ในบรรทัด'OUTPUT ที่แทรกไว้ WhatEverFieldNameYouWant'และสร้างฟิลด์ใดที่คุณต้องการในตาราง tempory ของคุณและเข้าถึงมันเพื่อใช้ตามที่คุณต้องการ

ฉันกำลังมองหาบางอย่างเช่นนี้มานานแล้วโดยมีการแบ่งรายละเอียดนี้ฉันหวังว่านี่จะช่วยได้


3

ใน SQL บริสุทธิ์ kools คำสั่งหลักเช่น:

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

วงเล็บเหลี่ยมกำหนดตาราง simbs แล้วคอลัมน์ En และ ID, วงเล็บเหลี่ยมกำหนดการแจงนับคอลัมน์ที่จะเริ่มต้นแล้วค่าสำหรับคอลัมน์ในกรณีของฉันหนึ่งคอลัมน์และหนึ่งค่า อะโพสโทรฟีใส่สตริง

ฉันจะอธิบายวิธีการของคุณ:

มันอาจจะไม่ใช่เรื่องง่ายที่จะเข้าใจ แต่ฉันหวังว่าจะเป็นประโยชน์ในการรับภาพรวมโดยใช้รหัสที่แทรกล่าสุด แน่นอนว่ามีวิธีการอื่นที่ง่ายกว่า แต่ฉันมีเหตุผลที่จะทำให้ฉัน ฟังก์ชั่นที่เกี่ยวข้องไม่ได้รวมอยู่เพียงแค่ชื่อและชื่อพารามิเตอร์

ฉันใช้วิธีนี้สำหรับปัญญาประดิษฐ์ทางการแพทย์วิธีตรวจสอบว่ามีสตริงที่ต้องการอยู่ในตารางกลาง (1) หากสตริงที่ต้องการไม่ได้อยู่ในตารางกลาง "simbs" หรือหากอนุญาตให้ซ้ำกันสตริงที่ต้องการจะถูกเพิ่มในตารางกลาง "simbs" (2) รหัส inseerted ล่าสุดถูกใช้เพื่อสร้างตารางที่เชื่อมโยง (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
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 ที่แทรกล่าสุด แต่วิธีที่ง่ายที่สุดที่ฉันพบคือเพียงแค่ดึงมันมาจาก 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 ที่แทรกล่าสุดจากบรรทัดคำสั่งด้านล่าง

INSERT INTO aspnet_GameProfiles (UserId, GameId) ค่า (@UserId, @GameId); SELECT @@ ตัวตน



-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) "; จากนั้นคุณสามารถเข้าถึง id ล่าสุดโดยสั่งให้เรียงจากมากไปน้อย

เลือกผู้ใช้ 1 อันดับแรกจาก aspnet_GameProfiles เรียงตาม UserId DESC


ระบุบุคคลที่ไม่ได้ใช้ IDENTITY_INSERT และเพิ่มแถวที่มี UserId ที่ใหญ่กว่ามาก
ldam

@Logan ฉันเข้าใจว่ามันใช้งานไม่ได้กับ charv เช่น id หรืออะไรบางอย่างที่ผสมกัน (charv + int) แต่คุณสามารถตั้งค่าคอลัมน์ประวัติศาสตร์ด้วย 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

นี่คือสิ่งที่ฉันคิดว่าดีจริงๆ ..... ตอนนี้คุณสามารถรับ id ที่เพิ่มขึ้นล่าสุดจากตารางใด ๆ ใน SQL -2005 สำหรับสิ่งนี้คุณเพียงแค่เรียกขั้นตอนนี้จากส่วนหน้า ขอให้สังเกตว่า passColumnName ควรมีชนิดข้อมูล INT
HEARTBEAT

2
ปัญหาที่ใหญ่ที่สุดของวิธีการนี้เทียบกับคำตอบที่ยอมรับคือคุณจะพบปัญหาหากลูกค้าหลายรายใส่ข้อมูลในเวลาเดียวกัน หากไคลเอ็นต์หนึ่งทำการเรียก sql สองครั้ง (ส่วนแทรกแรกให้ทำขั้นตอนที่เก็บไว้นี้สองครั้ง) และระหว่างสายทั้งสองสายไคลเอ็นต์อื่นก็ทำการแทรกคุณจะได้รับรหัสผิดกลับมา!
Oliver

4
สิ่งนี้จะไม่ส่งคืนผลลัพธ์ที่ถูกต้อง มันจะคืนค่าสูงสุดในคอลัมน์ (ซึ่งจะรวมแถวผู้ใช้หรือการดำเนินการอื่น ๆ ที่แทรกไว้) ไม่ใช่ค่าสุดท้ายที่คุณแทรก ดังนั้นสิ่งนี้จะทำงานกับระบบผู้ใช้คนเดียว การใช้หนึ่งในวิธีการที่มีอยู่แล้วภายใน (เช่น scope_identity ()) เป็นวิธีที่ถูกต้องเพียงวิธีเดียวในการรับ ID ที่แทรกล่าสุดภายในบริบท
NickG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.