【问题标题】:Get MAX id number from database table after deleting last record删除最后一条记录后从数据库表中获取 MAX id 号
【发布时间】:2015-12-03 22:08:37
【问题描述】:

我想为“产品”获取一个新的行 ID,为此我使用 MAX SQL 命令如下(该命令在插入新记录按钮单击事件中):

SqlCommand cmd = new SqlCommand("Select ISNULL(MAX(id)+1,0) from products", SqlCon);

问题是当有 ID 为 10、11、12 的行(12 是 MAX)并且我删除 id 12 记录时,当新的 id 行为 13 时,我得到 MAX+1 id 12(“id”字段为 PK身份增量为 1)。 我可以用其他方式吗?

示例:

id  prodect
--  -------
1     dog
2     cat
3     mouse
4     elefant

当我删除第 4 行时,我得到 MAX(id)+1 = 4,我想得到 5,因为这是下一行 id。

【问题讨论】:

  • 你想解决什么问题,你认为解决方案是“猜猜 products 表中的下一个身份是什么”
  • SQLServer?那为什么不使用标识列呢?
  • 这就是为什么使用 MAX+1 是一个的想法 - 它可能导致将相同的 ID 分配给不同的记录。只是不要这样做
  • 我正在尝试获取在按钮单击事件中添加的新行 ID。现在我按 MAX(id)+1 来做。问题是当我删除最后一行时,我得到与删除行相同的 id,而新行得到 id+1。我该怎么办?
  • 无法猜测下一个数字是多少,因为多个用户可以同时添加记录,尤其是在 ASP.NET 应用程序中。您可以通过在 INSERT 语句中使用 OUTPUT 子句来返回新 ID 的值

标签: c# asp.net sql-server


【解决方案1】:

一种可能的解决方案是不删除行。您可以添加一个标志并使其无效/删除。这样,您的行号将始终被保留,您的代码将为您提供最大 Id。

【讨论】:

  • IDENTITY 列值始终保留。 OP正在询问如何猜测下一个值是什么,这很奇怪
【解决方案2】:

我会试探一下我认为你所追求的东西。 :)

如果包含 SELECT SCOPE_IDENTITY();在您的 SQL 中,您将获得所需的 ID:

INSERT INTO products (
   * your fields *
)
VALUES (
   * your values *
);
SELECT SCOPE_IDENTITY();

然后在你的代码中你可以拥有:

var Id = Convert.ToInt32(cmd.ExecuteScalar());

这将为您提供已插入记录的 ID。

【讨论】:

  • 您不需要在 SQL Server 2005+ 中这样做(即在每个受支持的版本中)。您可以在末尾添加一个 OUTPUT 子句以返回新的 ID 值,例如:OUTPUT inserted.ID;
  • @Panagiotis - 很酷 - 我要尝试的新事物。这适用于其他数据库还是只是 MSSQL 的事情?
  • @Panagiotis Kanavos ,使用 UOTPUT 是否有任何风险?它的确切代码是什么?
【解决方案3】:

我认为 OP 试图解决错误的问题...

当你在 products 表中插入一个新产品时,你应该尝试直接使用 scope_identity 函数来检索新的 id(SQLServer!):

string sql = "insert into products(name) values('Yellow Cup'); SELECT SCOPE_IDENTITY();";
var sqlCommand = new SqlCommand(sql, conn);
var id = cSqlServer.ExecuteScalar();

【讨论】:

    【解决方案4】:

    在这种情况下,任何人都不会使用 MAX。最接近的解决方案是获取最近使用的身份值,然后将其增加 1(在您的情况下)或种子值,无论它是什么。

    select ident_current('products') + 1
    

    注意 - 虽然这暂时解决了您的目的,但请注意,“ident_current”也会返回您其他会话设置的身份值。简而言之,如果有一些请求/触发/执行导致 id 甚至在您的按钮单击完成之前递增,那么您将获得 insert_id 而不是删除一个。

    【讨论】:

      【解决方案5】:

      我怀疑实际的问题是How can I find the ID of the row I just inserted so I can use it as a foreign key in related tables or in an image file name?

      SQL Server 自 2005 年起在 INSERT、UPDATE、DELETE 语句中提供OUTPUT clause,该语句返回刚刚插入或修改的列的值。在插入语句的情况下,语法是:

      insert into Products (Product)
      OUTPUT inserted.ID 
      VALUES ('xxx')
      

      这是比IDENT_CURRENTSCOPE_IDENTITY 值更好的选择,因为它使用单个语句返回值并且返回的内容没有歧义:

      • 如果多个用户在事务外写入表,IDENT_CURRENT 可能会返回不同的值
      • SCOPE_IDENTITY 返回事务中生成的最后一个 ID,不管表是什么

      您可以返回多个列:

      insert into Products (Product)
      OUTPUT inserted.ID, inserted.Product
      VALUES ('xxx')
      

      如果您只返回一列,您可以使用 ExecuteScalar 执行此语句;如果您想返回更多列,则可以使用 ExecuteReader。

      对于 UPDATE 或 DELETE 语句,deleted 表包含已删除的值,inserted 包含新值

      注意 实体框架等 ORM 已经使用此类语句来检索自动生成的 ID 并更新保存的对象。在这种情况下,只需要读取已保存对象的 ID 属性即可。

      【讨论】:

      • 如何获取 OUTPUT id 值以及 'xxx' 值是什么?
      • xxx - 你想插入表格的任何内容。您只需更改您的INSERT 语句以添加OUTPUT ... 行。至于执行语句,使用ExecuteScalar而不是ExecuteNonQuery。现在如何插入条目?
      • 然后使用ExecuteScalar获取值
      • thatnks 它工作 :) 。我如何使用此 OUTPUT 将图像名称插入到同一 INSERT 语句中的图像列中?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多