最好的获取方式是什么 IDENTITY 插入的行?

我知道关于 @@IDENTITYIDENT_CURRENTSCOPE_IDENTITY 但不了解每个的优点和缺点。

有人可以解释一下它们之间的差异以及我应该何时使用它们吗?

有帮助吗?

解决方案

  • @@IDENTITY 返回为当前会话中所有范围内的任何表生成的最后一个标识值。 这里你需要小心, ,因为它是跨范围的。您可以从触发器获取值,而不是当前语句。

  • SCOPE_IDENTITY() 返回为当前会话和当前作用域中的任何表生成的最后一个标识值。 一般来说你想用什么.

  • IDENT_CURRENT('tableName') 返回为任何会话和任何范围中的特定表生成的最后一个标识值。这可以让您指定您想要来自哪个表的值,以防上面的两个不完全是您所需要的(很稀少)。另外,如@盖伊·斯塔巴克 提到,“如果您想获取尚未插入记录的表的当前 IDENTITY 值,则可以使用它。”

  • OUTPUT 条款INSERT 语句将允许您访问通过该语句插入的每一行。由于它的范围仅限于特定语句,因此 更直接 比上面的其他功能。不过,这有点 更详细 (您需要插入表变量/临时表,然后查询),即使在回滚语句的错误情况下它也会给出结果。也就是说,如果您的查询使用并行执行计划,这就是 唯一有保证的方法 用于获取身份(不关闭并行性)。然而,它被执行 触发器,不能用于返回触发器生成的值。

其他提示

我相信检索插入的 id 最安全、最准确的方法是使用输出子句。

例如(取自以下 微软软件定义网络 文章)

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

我和其他人说的是同样的事情,所以每个人都是对的,我只是想让它更清楚。

@@IDENTITY 返回客户端连接到数据库时插入的最后一个内容的 ID。
大多数情况下,这工作正常,但有时触发器会插入一个您不知道的新行,您将从这个新行中获取 ID,而不是您想要的 ID

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

IDENT_CURRENT 返回任何人插入的最后一个 ID。如果其他某个应用程序碰巧在不幸的时候插入了另一行,您将获得该行的 ID,而不是您的 ID。

如果您想安全起见,请始终使用 SCOPE_IDENTITY(). 。如果你坚持 @@IDENTITY 如果有人决定稍后添加触发器,您的所有代码都会崩溃。

最好的(阅读:最安全)获取新插入行标识的方法是使用 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)

添加

SELECT CAST(scope_identity() AS int);

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

NewId = command.ExecuteScalar()

将检索它。

微软软件定义网络

@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是类似的函数,因为它们返回插入到表的 IDENTITY 列中的最后一个值。

@@IDENTITY 和 SCOPE_IDENTITY 将返回当前会话中任何表中生成的最后一个标识值。但是,SCOPE_IDENTITY 仅返回当前范围内的值;@@IDENTITY不限于特定范围。

IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表。IDENT_CURRENT 返回为任何会话和任何范围中的特定表生成的标识值。有关详细信息,请参阅 IDENT_CURRENT。

  • IDENT_CURRENT 是一个以表作为参数的函数。
  • @@身份 当表上有触发器时可能会返回令人困惑的结果
  • 范围标识 大多数时候是你的英雄。

当您使用实体框架时,它在内部使用 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 或更高版本。

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

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

IDENT_CURRENT(表名) 是最后插入的标识,无论连接或范围如何。如果您想获取尚未插入记录的表的当前 IDENTITY 值,则可以使用此值。

我无法与其他版本的 SQL Server 对话,但在 2012 年,直接输出就可以了。您无需为临时表而烦恼。

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

顺便说一下,这种技术在插入多行时也适用。

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

输出

ID
2
3
4

总是 使用scope_identity(),不需要任何其他东西。

在插入语句之后,您需要添加此语句。并确保插入数据的表名。您将获得当前行,而不是刚刚受插入语句影响的行。

IDENT_CURRENT('tableName')

如果您正在查找最后添加/更新的 ID,这可能有点老派,但有很多人使用旧版 PHP,更准确地说是 Pre 5.5。更多详细信息请参见 http://php.net/manual/en/function.mysql-insert-id.php

$last = mysql_insert_id();

创建一个 uuid 并将其插入到列中。然后您可以轻松地使用 uuid 识别您的行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top