我有以下代码:

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


当我插入到此表中时,我有一个名为GamesProfileId的auto_increment int主键列,我如何才能在此之后最后插入一个所以我可以使用该ID插入另一个表?

#1 楼

对于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();


评论


如果表上有活动的触发器,则OUTPUT INSERTED.ID可能会产生问题

–armen
2014年1月22日上午10:06

嗯当我尝试此操作时,出现错误:“对象引用未设置为对象的实例。”即使它在执行后立即运行。

–卡尼
2014年5月17日上午10:39

我来自mysql,我无法理解此命令:Int32 newId =(Int32)myCommand.ExecuteScalar();

– Naguib Ihab
15年5月28日在1:23

“ OUTPUT INSERTED.ID”中的“ ID”是主键。我认为这是保留字。

– Danmbuen
2015年11月25日在9:24

有这个的MySQL版本吗?

– Roel
16年5月23日在7:22

#2 楼

您可以创建一个CommandText等于
INSERT INTO aspnet_GameProfiles(UserId, GameId) OUTPUT INSERTED.ID VALUES(@UserId, @GameId)

的SqlCommand并执行int id = (int)command.ExecuteScalar
此MSDN文章将为您提供一些其他技术。

#3 楼

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

这将起作用。

#4 楼

我也有同样的需求,并找到了答案。.

这会在公司表(comp)中创建一条记录,它将获取在公司表中创建的自动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'用于保存我们将要获取的公司自动生成的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


-已插入“输出”。上面的行用于从当前正在创建的记录的任何字段中获取数据。我们想要的数据是ID自动编号。因此,请确保它为您的表输入正确的字段名称,我的名称是'comp_id'。然后将其放到我们之前创建的临时表中。已保存。由于此临时表中只有一条记录,只有一个字段,因此它将仅选择所需的ID号并将其放入“ @recID”。 '@recID'现在具有您想要的ID号,您可以像下面在我所使用的方式使用它。

  VALUES (@comp_name, @comp_regno, @comp_email)

  SET @recID = (SELECT tempID FROM @tableVar)


-这样就可以了。您实际上可以在插入的“ OUTPUT.WhatEverFieldNameYouWant”行中获取所需的内容,并在临时表中创建所需的字段并访问它以使用所需的内容。

我正在寻找东西多年来一直如此,通过详细的细分,希望对您有所帮助。

#5 楼

在纯SQL中,主要语句如下:

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


方括号定义表simb,然后是列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
    }


#6 楼

我尝试了上面的方法,但是他们没有用,我发现了这种想法,对我来说很好。

var ContactID = db.GetLastInsertId();


它的代码更少,我很容易插入。

希望这对某人有帮助。

#7 楼

您还可以在SQL Server中使用对SCOPE_IDENTITY的调用。

#8 楼

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


#9 楼

有各种各样的方法来获取最后插入的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;


希望对您有所帮助...

#10 楼

在查询中使用SELECT SCOPE_IDENTITY()

#11 楼

之后:

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


执行此操作

int id = (int)command.ExecuteScalar;


它将起作用

#12 楼

插入任何行后,您可以通过查询以下行获得最后插入的ID。

插入aspnet_GameProfiles(UserId,GameId)
VALUES(@UserId,@GameId);
SELECT @@ IDENTITY

#13 楼

插入到aspnet_GameProfiles(UserId,GameId)VALUES(@UserId,@GameId)“;
,那么您就可以通过按desc方式对表进行排序来访问最后一个ID。

选择前1个Userid FROM aspnet_GameProfiles按UserId DESC排序。

评论


假设有人没有使用IDENTITY_INSERT并添加了一个具有更大UserId的行。

–ldam
18-09-25在11:18

@Logan我明白,它不能仅使用id等charv或混合(charv + int)的字符,但是您可以设置带有增量int的历史列并完成此操作。

–亚历山大
18-10-25在9:26

#14 楼

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。

–心跳
2012年5月15日7:05



这种针对公认答案的方法最大的问题是,如果同时插入多个客户端,则会遇到问题。如果客户端进行两次sql调用(第一个插入,然后执行此存储过程),而在这两个调用之间,另一个客户端也进行了插入,则会返回错误的ID!

–奥利弗
2012年5月15日在7:27

这将不会返回正确的结果。它将返回列中的最大值(其中将包括其他用户或操作已插入的行),而不是您最后插入的值。因此,这仅适用于单用户系统。使用内置方法之一(例如scope_identity())是获取上下文中最后插入的ID的唯一正确方法。

– NickG
13年5月29日在14:28