SQL Server - возвращаемое значение после INSERT

Я пытаюсь вернуть значение ключа после оператора INSERT. Пример: у меня есть таблица с атрибутами name и id. id является сгенерированным значением.

    INSERT INTO table (name) VALUES('bob');

Теперь я хочу вернуть идентификатор на том же этапе. Как это сделать?

Мы используем Microsoft SQL Server 2008.

15 ответов

Решение

Нет необходимости в отдельном SELECT...

INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');

Это работает и для столбцов не-IDENTITY (например, GUID)

Использование SCOPE_IDENTITY() чтобы получить новое значение идентификатора

INSERT INTO table (name) VALUES('bob');

SELECT SCOPE_IDENTITY()

http://msdn.microsoft.com/en-us/library/ms190315.aspx

INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY();

Это самая безопасная ставка, поскольку существует известная проблема с конфликтом предложения OUTPUT для таблиц с триггерами. Делает это довольно ненадежным, даже если в вашей таблице в настоящее время нет триггеров - кто-то, добавивший один из них, сломает ваше приложение. Time Bomb своего рода поведение.

Смотрите статью MSDN для более глубокого объяснения:

http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx

Entity Framework выполняет что-то похожее на ответ gbn:

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO Customers(FirstName)
OUTPUT inserted.CustomerID INTO @generated_keys
VALUES('bob');

SELECT t.[CustomerID]
FROM @generated_keys AS g 
   JOIN dbo.Customers AS t 
   ON g.Id = t.CustomerID
WHERE @@ROWCOUNT > 0

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

вставки могут генерировать более одной строки, поэтому переменная может содержать более одной строки, поэтому вам может быть возвращено более одной ID

Я понятия не имею, почему EF внутренне присоединяет эфемерную таблицу обратно к реальной таблице (при каких обстоятельствах эти два не совпадают).

Но это то, что делает EF.

SQL Server 2008 или новее только. Если это 2005, то вам не повезло.

Есть много способов выйти после вставки

Когда вы вставляете данные в таблицу, вы можете использовать предложение OUTPUT, чтобы вернуть копию данных, которые были вставлены в таблицу. Предложение OUTPUT принимает две основные формы: OUTPUT и OUTPUT INTO. Используйте форму ВЫВОД, если вы хотите вернуть данные вызывающему приложению. Используйте форму OUTPUT INTO, если вы хотите вернуть данные в таблицу или в табличную переменную.

DECLARE @MyTableVar TABLE (id INT,NAME NVARCHAR(50));

INSERT INTO tableName
(
  NAME,....
)OUTPUT INSERTED.id,INSERTED.Name INTO @MyTableVar
VALUES
(
   'test',...
)

IDENT_CURRENT: возвращает последний идентификатор, созданный для конкретной таблицы или представления в любом сеансе.

SELECT IDENT_CURRENT('tableName') AS [IDENT_CURRENT]

SCOPE_IDENTITY: возвращает последний идентификатор из того же сеанса и той же области. Область видимости - это хранимая процедура / триггер и т. Д.

SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];  

@@IDENTITY: возвращает последний идентификатор из того же сеанса.

SELECT @@IDENTITY AS [@@IDENTITY];

@@IDENTITY - системная функция, которая возвращает последнее введенное значение идентификатора.

Есть несколько способов получить последний вставленный идентификатор после команды вставки.

  1. @@IDENTITY: Возвращает последнее значение идентификатора, сгенерированное для соединения в текущем сеансе, независимо от таблицы и области действия оператора, создавшего значение.
  2. SCOPE_IDENTITY(): Возвращает последнее значение идентификатора, сгенерированное оператором вставки в текущей области в текущем соединении, независимо от таблицы.
  3. IDENT_CURRENT(‘TABLENAME’): Возвращает последнее значение идентификатора, созданное в указанной таблице, независимо от любого соединения, сеанса или области. IDENT_CURRENT не ограничен областью действия и сеансом; он ограничен указанной таблицей.

Теперь, кажется, сложнее решить, какой из них будет в точности соответствовать моим требованиям.

Я в основном предпочитаю SCOPE_IDENTITY().

Если вы используете select SCOPE_IDENTITY() вместе с TableName в операторе вставки, вы получите точный результат в соответствии с вашими ожиданиями.

Источник: CodoBee

Лучшее и самое верное решение - использовать SCOPE_IDENTITY. просто вы должны получить идентификатор области после каждой вставки и сохранить ее в переменной, потому что вы можете вызвать две вставки в одной и той же области. @identity и @@identity могут быть они работают, но они не являются безопасной областью. Вы можете иметь проблемы в большом приложении

  declare @duplicataId int
  select @duplicataId =   (SELECT SCOPE_IDENTITY())

Более подробно здесь Microsoft документы

Вы можете использовать scope_identity, чтобы выбрать идентификатор строки, которую вы только что вставили в переменную, а затем просто выбрать любые столбцы из этой таблицы, где id = идентификатор, который вы получили из scope_identity.

См. Здесь для получения информации MSDN http://msdn.microsoft.com/en-us/library/ms190315.aspx

Рекомендуется использовать SCOPE_IDENTITY() для получения нового значения идентификатора, но НЕ использовать "OUTPUT Inserted.ID"

Если оператор вставки вызывает исключение, я за исключением этого, бросаю его напрямую. Но «OUTPUT Inserted.ID» вернет 0, что, возможно, и не исключено.

Вы можете добавить оператор выбора к вашему оператору вставки. Integer myInt = Вставить в таблицу1 (FName) значения ("Фред"); Выберите Scope_Identity(); Это вернет значение идентификатора при выполнении скалера.

Вот как я использую OUTPUT INSERTED при вставке в таблицу, которая использует ID в качестве столбца идентификаторов в SQL Server:

'myConn is the ADO connection, RS a recordset and ID an integer
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())")
ID=RS(0)

Это может быть немного старой школой, но есть много людей, использующих более старый PHP, а точнее Pre 5.5. Более подробную информацию можно найти на http://php.net/manual/en/function.mysql-insert-id.php

$last = mysql_insert_id();

* Порядок параметров в строке подключения иногда важен. * Расположение параметра Provider может нарушить курсор набора записей после добавления строки. Мы видели такое поведение с поставщиком SQLOLEDB.

После добавления строки поля строки недоступны, ЕСЛИ поставщик не указан в качестве первого параметра в строке подключения. Когда поставщик находится где-либо в строке подключения, кроме как в качестве первого параметра, вновь вставленные поля строки недоступны. Когда мы переместили провайдера к первому параметру, поля строки волшебным образом появились.

После вставки в таблицу со столбцом идентификаторов вы можете обратиться к @@IDENTITY, чтобы получить значение: http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx

Другие вопросы по тегам