получить новый идентификатор записи SQL
Как я могу вернуть автогенерированный идентификатор для новой записи, которую я только что вставил? (Используя ASP classic и MSSQL 2005)
8 ответов
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 в 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;
SELECT @@IDENTITY обычно работает, но может вернуть идентификатор записи, вставленной из-за триггера или чего-то еще, а не оригинала.
выберите SCOPE_IDENTITY - это то, что я бы рекомендовал. Возвращает значения, вставленные только в текущей области.
существует также " IDENT_CURRENT (tablename)", который возвращает последний идентификатор, вставленный для определенной таблицы.
есть три способа получить последнее удостоверение в sql.
они уже упоминались другими, но для полноты:
- @@IDENTITY-может также возвращать идентификаторы, созданные в других объектах в той же области (триггеры think)
- 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 он слишком далеко зашел, чтобы показать примеры первых двух из клиентского кода.
SELECT @@Identity или SELECT SCOPE_IDENTITY() оба работают, однако выбор SCOPE_Identity () безопаснее, поскольку он возвращает последний автоматически сгенерированный идентификатор в текущей области. Например, предположим, что у нас есть таблица под названием ScopeIDTable, и в этой таблице у нас есть триггер. Этот триггер будет вставляться в запись в TriggerIdTable обе таблицы имеют столбец автоматического приращения.
Если вы используете SELECT @@Identity, вы получите последнее автоматическое приращение в этом сеансе, которое будет Id генерируется из триггера (TriggerIdTable).
Если вы используете SELECT SCOPE_IDENTITY (), вы получите идентификатор из ScopeIdTable.
выполнить запрос
select scope_identity()
используя то же соединение с базой данных, прежде чем делать что-либо еще с ним. В результате, как вы, вероятно, ожидаете, набор записей, содержащий одну строку с одним полем. Вы можете получить доступ к полю с помощью индекса 0 или дать ему имя, если хотите:
select scope_identity() as lastId
Я всегда задавался вопросом, почему бы когда-нибудь захотеть использовать
@@identity
С
select scope_identity()
очевидно, что это самый экономный способ выполнить то, о чем просит Scot.
где несколько записей должны вставляться сразу в установленном порядке, это может стать более интересным.
Я иногда использовал GUID, сгенерированные на стороне клиента (но для классического ASP вам, вероятно, потребуется использовать утилиту для генерации значений) или, чаще, ограничение NEWSQUENTIALID () в столбце ключа GUID на сервере.
Я знаю, что не все любят GIUDS, хотя по некоторым вполне веским причинам (их размер и как это влияет на индексирование / подкачку для один.)
http://www.sqlmag.com/Articles/Index.cfm?ArticleID=50164&pg=2
спасибо всем, кто предложил выбрать 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 в любое время, когда я ссылаюсь на вновь созданный идентификатор.