【问题标题】:Return ID on INSERT?在 INSERT 上返回 ID?
【发布时间】:2011-05-06 10:58:55
【问题描述】:

我有一个 INSERT 查询,我希望数据库返回我刚刚插入的行的 ID。

sqlString = "INSERT INTO MagicBoxes (OwnerID, Key, Name, Permissions, Active, LastUpdated) VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) SET @ID = SCOPE_IDENTITY();";
cmd = new SqlCommand(sqlString, con);
cmd.Parameters.AddWithValue("@OwnerID", OwnerID);
cmd.Parameters.AddWithValue("@BoxKey", BoxKey);
cmd.Parameters.AddWithValue("@BoxName", BoxName);
cmd.Parameters.AddWithValue("@Username", Username);
cmd.Parameters.AddWithValue("@Date", DateTime.Now);
cmd.ExecuteNonQuery();

我目前有这个,我不确定接下来我需要做什么......

【问题讨论】:

  • 无法得到你的问题,你想要刚刚插入的行的种子值吗?

标签: c# sql sql-server insert


【解决方案1】:

您只需将@ID 添加到 params 集合中,然后像这样检索它,

cmd.Parameters.Add("@ID", SqlDbType.Int, 4).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
//Now just read the value of: cmd.Parameters["@ID"].value

或者,如果您更喜欢这种语法:

SqlParameter param = new SqlParameter("@ID", SqlDbType.Int, 4);
param.Direction = ParameterDirection.Output;
cmd.Parameters.Add(param);

【讨论】:

  • Argument 4: cannot convert from 'System.Data.ParameterDirection' to 'string'
  • @Danpe = 道歉,上面已更正 - 我总是发现添加的输出参数比它需要的要笨重一些
  • 我无法使这个工作,执行命令后参数为空。这里的另一个答案使用 ExecuteScalar 并且似乎产生了正确的值。
【解决方案2】:

自 SQL Server 2008 起,在 TSQL 的语法中添加了 OUTPUT clause。这允许您将受 DML 查询影响的数据添加到表格数据流中。

尽管在查询返回正确信息后查询 SCOPE_IDENTITY() 会强制 SQL Server 执行 2 个查询,其中输出子句将其限制为一个查询。

知道了这一点,正在执行的查询可以改变如下(假设[Id]是身份的名称):

INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
OUTPUT INSERTED.Id
VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date)

另一个问题是没有处理SqlCommand。 ADO.net 中的大部分Sql... 对象都实现了IDisposable,应妥善处理。

将所有内容放在一起,我将按如下方式实现这段代码:

        using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ConnectionString))
        using (var cmd = new SqlCommand(@"
                INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
                OUTPUT INSERTED.Id
                VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) ", conn))
        {
            cmd.Parameters.AddRange(new[]
                {
                    new SqlParameter("@OwnerID", SqlDbType.Int).Value = OwnerID,
                    new SqlParameter("@BoxKey", SqlDbType.VarChar).Value = BoxKey, 
                    new SqlParameter("@BoxName", SqlDbType.VarChar).Value = BoxName, 
                    new SqlParameter("@Date", SqlDbType.DateTime).Value = DateTime.Now 
                });

            conn.Open();

            var id = (int)cmd.ExecuteScalar();
        }

【讨论】:

  • 这是最好的答案。
【解决方案3】:

你有两个选择;您可以声明一个名为@IDOutput 参数;或者 - 您可以将结尾更改为 SELECT SCOPE_IDENTITY() 并使用:

int id = (int)cmd.ExecuteScalar();

我更喜欢形参方式,但ExecuteScalar 效果很好。

【讨论】:

    【解决方案4】:

    将此添加到您的参数中

    SqlParameter IDParameter = new SqlParameter("@ID",SqlDbType.Int);
    IDParameter.Direction = ParameterDirection.Output;
    cmd.Parameters.Add(IDParameter);
    

    执行后可以取回id

    int id = (int)IDParameter.Value;
    

    【讨论】:

      【解决方案5】:

      为什么不调用存储过程。将值传递给存储过程以获取插入的值,并从 SP 返回使用 SCOPE_IDENTITY(). 插入的最后一个种子值。希望有所帮助。

      【讨论】:

      • 拥有存储过程不会改变任何东西;这是关于参数/结果传递的,这将是相同的
      • 是的,你是对的,我的意思是调用 SP 和 from SP 返回插入后的最后一个种子值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      • 2012-11-16
      • 2013-03-28
      • 1970-01-01
      • 2013-04-28
      相关资源
      最近更新 更多