获取新的SQL记录ID

时间:2009-02-26 15:09:38

标签: sql sql-server sql-server-2005 asp-classic

如何为刚刚插入的新记录取回自动生成的ID? (使用ASP classic和MSSQL 2005)

8 个答案:

答案 0 :(得分:25)

SELECT SCOPE_IDENTITY() 

使用@@ IDENTITY可能会产生意外结果,因此请谨慎使用。将记录插入其他表的触发器将导致@@ IDENTITY值发生更改 - 其中SCOPE_IDENTITY()将仅从您当前作用域中为您提供最后一个标识。

这是一个示例,它将显示@@ IDENTITY和SCOPE_INSERT()之间的区别以及它们如何返回不同的值。

use tempdb
go
create table table1
    (ID int identity)
go
create table table2
    (ID int identity(100, 1))
go
create trigger temptrig 
    on table1 
    for insert
as
begin

    insert  table2 
     default values;

end
go
insert  table1 
default values;
select  SCOPE_IDENTITY(), 
        @@IDENTITY

此处没有人讨论的另一个选项是使用SQL 2005中的OUTPUT子句。在这种情况下,您只需要将insert子句添加到insert中,然后从代码中捕获该记录集。这在插入多个记录时效果很好,而不仅仅是1 ...

use tempdb
go
create table table1
    (ID int identity)
go
insert   table1 
output   inserted.ID
default values;
--OR...
insert   table1 
output   inserted.$identity
default values;

答案 1 :(得分:9)

SELECT @@ IDENTITY通常有效,但可以返回由于触发器或其他内容而插入的记录的标识,而不是原始标识。

SELECT SCOPE_IDENTITY是我推荐的。它返回仅在当前范围内插入的值。

还有一个“IDENT_CURRENT(tablename)”,它返回为特定表插入的最后一个标识。

答案 2 :(得分:9)

有三种方法可以在sql 中获取最后一个身份

他们已经提到了他们,但为了完整性:

  • @@ IDENTITY - 也可以返回在同一范围内的其他对象中创建的ID(想想触发器)
  • IDENT_CURRENT - 仅限于一个表,但不限于您的范围,因此它可以为繁忙的表格提供不良结果
  • Scope_Idenity() - 仅限于请求的范围。使用这99%的时间

此外,有三种方法可以获取该ID并将其返回到您的客户端代码:

  • 在存储过程中使用输出参数

    INSERT INTO [MyTable] ([col1],[col2],[col3]) VALUES (1,2,3); 
    SELECT @OutputParameterName = Scope_Identity();
    
  • 使用返回值。

    INSERT INTO [MyTable] ([col1],[col2],[col3]) VALUES (1,2,3); 
    Return Scope_Identity();
    
  • 在结果集中选择id。例如,你的sql语句看起来像这样:

    Dim ResultID As Integer
    Dim strSQL As String
    strSQL = "INSERT INTO [MyTable] ([col1],[col2],[col3]) VALUES (1,2,3); SELECT Scope_Identity();"
    rsResults.Open strSQL, oConn
    ResultID = rsResults("ID")
    

不幸的是(或者幸运的是,从我的角度来看)我的经典ASP它远远地显示了客户端代码中前两个的例子。

答案 3 :(得分:3)

SELECT @@ Identity或SELECT SCOPE_IDENTITY()都有效但选择SCOPE_Identity()更安全,因为它返回当前范围内的最后一个自动生成的ID。因此,假设我们有一个名为ScopeIDTable的表,在此表中我们有一个触发器。此触发器将插入到TriggerIdTable的记录中,两个表都有一个自动增量列。

如果您使用SELECT @@ Identity,您将获得该会话中的最后一次自动增量,该增量将是从触发器内生成的Id(TriggerIdTable)。

如果您使用SELECT SCOPE_IDENTITY(),您将从ScopeIdTable获取id。

答案 4 :(得分:1)

您运行查询

select scope_identity()

使用相同的数据库连接,然后再对其进行任何其他操作。正如您所料,结果是包含具有单个字段的单个行的记录集。您可以使用索引0访问该字段,或者如果您愿意,可以为其指定名称:

select scope_identity() as lastId

答案 5 :(得分:1)

我总是想知道为什么人们会想要使用

@@identity

select scope_identity() 

显然是实现苏格兰人要求的最省钱方式。

答案 6 :(得分:0)

如果需要以基于集合的方式一次插入多个记录,它会变得更有趣。

我有时使用GUID生成的客户端(但对于经典ASP,您可能需要使用实用程序来生成值),或者更常见的是,在服务器端的GUID键列上使用NEWSQUENTIALID()约束。 / p>

我知道不是每个人都喜欢GIUDS,因为一些非常正当的理由(它们的大小以及它如何影响索引/分页)。

http://www.sqlmag.com/Articles/Index.cfm?ArticleID=50164&pg=2

答案 7 :(得分:0)

感谢所有建议使用SELECT SCOPE_IDENTITY()的人。我能够创建一个存储过程:

USE [dbname]
GO 
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[spInsert]
(
   @Nn varchar(30)
)
AS
BEGIN TRANSACTION InsertRecord 
   INSERT INTO A (Nn) 
   VALUES (@Nn) 
   SELECT NewID = SCOPE_IDENTITY()   -- returns the new record ID of this transaction
   COMMIT TRANSACTION InsertRecord

并使用VB调用sproc:

Dim strNn '<- var to be passed'
Set cn = Server.CreateObject("ADODB.Connection") 
connectString = "DSN" 
cn.Open connectString, "user", "PW0rd" 
Set rs = Server.CreateObject("ADODB.Recordset") 
set rs = cn.Execute("EXEC [dbname].[dbo].[A] @Nn=" & strNn)
'return the value'
resultID = rs(0)

我现在可以随时使用resultID来引用新创建的ID。