получить новый идентификатор записи SQL - PullRequest
10 голосов
/ 26 февраля 2009

Как я могу вернуть автоматически сгенерированный идентификатор для новой записи, которую я только что вставил? (С использованием ASP classic и MSSQL 2005)

Ответы [ 8 ]

25 голосов
/ 26 февраля 2009
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

Другой вариант, который здесь никто не обсуждал, - это использовать предложение OUTPUT, которое есть в SQL 2005. В этом случае вам просто нужно добавить предложение output в вашу вставку, а затем перехватить этот набор записей из вашего кода. Это хорошо работает при вставке нескольких записей вместо 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;
9 голосов
/ 26 февраля 2009

Существует три способа получить последний идентификатор в sql .

Они уже упоминались другими, но для полноты:

  • @@ IDENTITY - также может возвращать идентификаторы, созданные в других объектах в той же области (думаю, триггеры)
  • IDENT_CURRENT - ограничено таблицей, но не вашей областью, поэтому может давать плохие результаты для занятых таблиц
  • Scope_Idenity () - ограничено объемом запроса. Используйте это 99% времени

Кроме того, есть три способа получить этот идентификатор и вернуть его в код вашего клиента:

  • Использование выходного параметра в хранимой процедуре

    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();
    
  • Выберите идентификатор в наборе результатов. Например, ваш 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 слишком далеко зашел, чтобы показать примеры первых двух из клиентского кода.

9 голосов
/ 26 февраля 2009

SELECT @@ IDENTITY обычно работает, но может вернуть идентификатор записи, вставленной из-за триггера или чего-то другого, а не оригинала.

SELECT SCOPE_IDENTITY - это то, что я бы порекомендовал. Возвращает значения, вставленные только в текущую область.

Существует также «IDENT_CURRENT (имя таблицы)», который возвращает последний идентификатор, вставленный для конкретной таблицы.

3 голосов
/ 26 февраля 2009

SELECT @@ Identity или SELECT SCOPE_IDENTITY () оба работают, однако выбор SCOPE_Identity () безопаснее, поскольку он возвращает последний автоматически сгенерированный идентификатор в текущей области. Например, предположим, что у нас есть таблица с именем ScopeIDTable и для этой таблицы у нас есть триггер. Этот триггер вставит в запись в TriggerIdTable, обе таблицы имеют столбец с автоинкрементом.

Если вы используете SELECT @@ Identity, вы получите последнее автоинкремент в этом сеансе, который будет идентификатором, сгенерированным из триггера (TriggerIdTable).

Если вы используете SELECT SCOPE_IDENTITY (), вы получите идентификатор из вашей ScopeIdTable.

1 голос
/ 01 марта 2009

Мне всегда было интересно, почему кто-то захочет использовать

@@identity

с

select scope_identity() 

очевидно, это самый безопасный способ выполнить то, что просит Скот.

1 голос
/ 26 февраля 2009

Вы запускаете запрос

select scope_identity()

используя то же соединение с базой данных, прежде чем делать что-либо еще с ним. Результатом является, как вы, вероятно, ожидаете, набор записей, содержащий одну строку с одним полем. Вы можете получить доступ к полю, используя индекс 0, или вы можете дать ему имя, если предпочитаете:

select scope_identity() as lastId
0 голосов
/ 18 апреля 2009

Спасибо всем, кто предложил 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

и вызовите sproc с помощью VB:

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 в любое время, когда ссылаюсь на вновь созданный идентификатор.

0 голосов
/ 26 февраля 2009

Если несколько записей необходимо вставить одновременно на основе набора, это может стать более интересным.

Я иногда использовал GUID, сгенерированные на стороне клиента (но для классического ASP вам, вероятно, понадобится утилита для генерации значений) или, чаще, ограничение NEWSQUENTIALID () для столбца ключа GUID на стороне сервера.

Я знаю, что не всем нравится GIUDS, хотя по некоторым вполне обоснованным причинам (их размер и как это влияет на индексирование / подкачку для одного).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...