使用select语句获取自动递增主键的最后一个值是否安全?

本文关键字:最后一个 是否 安全 语句 select 获取 使用 | 更新日期: 2023-09-27 18:04:49

让我们假设SQL Server 2012中有以下简单的表:

CREATE TABLE Person (
   Id INT IDENTITY(1, 1) PRIMARY KEY,
   Name NVARCHAR(50)
)

和c#中相应的类:

public class Person 
{
    public int Id {get; set;}
    public string Name {get; set;}
}

现在考虑以下CreatePerson方法(伪代码):

public static Person CreatePerson(string name) {
    ...
    DB.Execute("INSERT INTO Person(Name) VALUES (name)", name);
    int lastId = DB.Get("SELECT MAX(Id) FROM Person");
    return new Person {Id = lastId, Name=name};
}

该方法在数据库中创建一个新的person行,构建一个新的person对象,然后返回创建的对象,该对象应该包含数据库生成的Id。

通过使用以下SELECT语句获得最后生成的Id是安全的和/或正确的(从并发性角度来看)吗?

SELECT MAX(Id) FROM Person

我很关心下面的场景:

    用户一个
  1. 插入一个person 1
  2. 用户B
  3. 插入一个person 2
  4. USER A读取最后一个Id并认为它是person 1的Id

注意,这里的 USER A和USER B指的是处理对数据库的两个独立查询的线程。

使用select语句获取自动递增主键的最后一个值是否安全?

如果您想获得在特定范围内某人插入的最后一个标识值,请使用Scope_Identity()

如果您想获得跨作用域插入到特定表的最后一个标识值,您可以使用@@identity

如果您想获得一个特定表的当前标识值,使用Ident_Current ('Yourtablename')

不,这是不安全的,您可以使用这个过程进行数据插入,并通过使用scopre_Identity函数获得您的lastd

create PROCEDURE Your_procedure_for_insert
@Name      VARCHAR(50),
@lastID      INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Person
            (
            Name                
            )
VALUES  
            (
            @Name 
            );
SET @lastID = SCOPE_IDENTITY();
END;