首页 文章

获取插入行的标识的最佳方法是什么?

提问于
浏览
931

获取 IDENTITY 插入行的最佳方法是什么?

我知道 @@IDENTITYIDENT_CURRENTSCOPE_IDENTITY ,但不了解每个人的利弊 .

有人可以解释一下这些差异,以及何时我应该使用它们?

11 回答

  • 1228
    • @@IDENTITY返回在所有范围内为当前会话中的任何表生成的最后一个标识值 . You need to be careful here ,因为它跨越范围 . 您可以从触发器获取值,而不是当前语句 .

    • SCOPE_IDENTITY()返回为当前会话中的任何表和当前范围生成的最后一个标识值 . Generally what you want to use .

    • IDENT_CURRENT('tableName')返回在任何会话和任何范围内为特定表生成的最后一个标识值 . 这允许您指定您想要该值的表,以防上述两个表不是您需要的( very rare ) . 另外,正如@ Guy Starbuck所述,"You could use this if you want to get the current IDENTITY value for a table that you have not inserted a record into."

    • INSERT 语句的OUTPUT clause将允许您访问通过该语句插入的每一行 . 由于's scoped to the specific statement, it' s more straightforward 比上面的其他功能 . 但是,它有点 more verbose (您需要插入表变量/临时表然后查询)并且即使在回滚语句的错误情况下也会给出结果 . 也就是说,如果您的查询使用并行执行计划,那么 only guaranteed method 用于获取标识(缺少关闭并行性) . 但是,它在触发器之前执行,不能用于返回触发器生成的值 .

  • 12

    我说的和其他人一样,所以每个人都是对的,我只是想让它更清楚 .

    @@IDENTITY 返回客户端连接到数据库的最后一个内容的id .
    大部分时间这种方法都可以正常工作,但有时触发器会插入一个新行,你不会从这个新行获取ID,而不是你想要的那个

    SCOPE_IDENTITY() 解决了这个问题 . 它返回您在发送到数据库的SQL代码中插入的最后一个内容的id . 如果触发器去创建额外的行,它们将不会导致返回错误的值 . 万岁

    IDENT_CURRENT 返回任何人插入的最后一个ID . 如果某个其他应用程序恰好在不合适的时间插入另一行,您将获得该行的ID而不是您的ID .

    如果您想安全地玩,请始终使用 SCOPE_IDENTITY() . 如果您坚持使用 @@IDENTITY 并且有人决定稍后添加触发器,那么您的所有代码都将中断 .

  • 13

    SELECT CAST(scope_identity() AS int);
    

    到插入sql语句的末尾,然后

    NewId = command.ExecuteScalar()
    

    将检索它 .

  • 99

    我无法与其他版本的SQL Server通信,但在2012年,直接输出工作得很好 . 您不需要打扰临时表 .

    INSERT INTO MyTable
    OUTPUT INSERTED.ID
    VALUES (...)
    

    顺便说一下,这种技术在插入多行时也有效 .

    INSERT INTO MyTable
    OUTPUT INSERTED.ID
    VALUES
        (...),
        (...),
        (...)
    

    产量

    ID
    2
    3
    4
    
  • 13

    @@IDENTITY 是使用当前SQL连接插入的最后一个标识 . 这是从插入存储过程返回的一个很好的值,您只需要为新记录插入标识,并且不关心之后是否添加了更多行 .

    SCOPE_IDENTITY 是使用当前SQL连接插入的最后一个标识,并且在当前范围内 - 也就是说,如果在插入后基于触发器插入了第二个IDENTITY,则它不会反映在SCOPE_IDENTITY中,只会反映您执行的插入 . 坦率地说,我从来没有理由使用它 .

    无论连接或范围如何, IDENT_CURRENT(tablename) 都是插入的最后一个标识 . 如果要获取尚未插入记录的表的当前IDENTITY值,可以使用此方法 .

  • 21

    我相信检索插入的id的最安全和最准确的方法是使用output子句 .

    例如(取自以下MSDN文章)

    USE AdventureWorks2008R2;
    GO
    DECLARE @MyTableVar table( NewScrapReasonID smallint,
                               Name varchar(50),
                               ModifiedDate datetime);
    INSERT Production.ScrapReason
        OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
            INTO @MyTableVar
    VALUES (N'Operator error', GETDATE());
    
    --Display the result set of the table variable.
    SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
    --Display the result set of the table.
    SELECT ScrapReasonID, Name, ModifiedDate 
    FROM Production.ScrapReason;
    GO
    
  • 158

    使用Entity Framework时,它在内部使用 OUTPUT 技术返回新插入的ID值

    DECLARE @generated_keys table([Id] uniqueidentifier)
    
    INSERT INTO TurboEncabulators(StatorSlots)
    OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
    VALUES('Malleable logarithmic casing');
    
    SELECT t.[TurboEncabulatorID ]
    FROM @generated_keys AS g 
       JOIN dbo.TurboEncabulators AS t 
       ON g.Id = t.TurboEncabulatorID 
    WHERE @@ROWCOUNT > 0
    

    输出结果存储在临时表变量中,连接回表,并将行值返回表中 .

    注意:我不知道为什么EF将内部表连接到真实表(在什么情况下两者不匹配) .

    但这就是EF所做的 .

    此技术( OUTPUT )仅适用于SQL Server 2008或更高版本 .

  • 8

    ALWAYS 使用scope_identity(),不需要任何其他东西 .

  • 6

    MSDN

    @@ IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT是类似的函数,因为它们返回插入表的IDENTITY列的最后一个值 . @@ IDENTITY和SCOPE_IDENTITY将返回当前会话中任何表中生成的最后一个标识值 . 但是,SCOPE_IDENTITY仅在当前范围内返回值; @@ IDENTITY不限于特定范围 . IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表格 . IDENT_CURRENT返回在任何会话和任何范围内为特定表生成的标识值 . 对于更多信息,请参阅IDENT_CURRENT .

  • 0

    在插入语句之后,您需要添加它 . 并确保插入数据的表名 . 您的插入语句将立即获取当前行no行 .

    IDENT_CURRENT('tableName')
    
  • 58

    获取新插入行的标识的最佳(读取:最安全)方法是使用 output 子句:

    create table TableWithIdentity
               ( IdentityColumnName int identity(1, 1) not null primary key,
                 ... )
    
    -- type of this table's column must match the type of the
    -- identity column of the table you'll be inserting into
    declare @IdentityOutput table ( ID int )
    
    insert TableWithIdentity
         ( ... )
    output inserted.IdentityColumnName into @IdentityOutput
    values
         ( ... )
    
    select @IdentityValue = (select ID from @IdentityOutput)
    

相关问题