Как да върна нова стойност на колона IDENTITY от оператор SELECT на SQLServer?

Вмъквам в таблица на SQLServer с автоматично нарастващо ключово поле. (Вярвам, че това се нарича колона IDENTITY в SQLServer.)

В Oracle мога да използвам ключовата дума RETURNING, за да дам на моя оператор INSERT набор от резултати като заявка SELECT, която ще върне генерираната стойност:

INSERT INTO table
(foreign_key1, value)
VALUES
(9, 'text')
RETURNING key_field INTO :var;

Как да постигна това в SQLServer?

Бонус: Добре, хубави отговори досега, но как да ги събера в едно твърдение, ако е възможно? :)


person skiphoppy    schedule 10.06.2009    source източник


Отговори (7)


Като цяло не може да се направи в едно изявление.

Но SELECT SCOPE_IDENTITY() може (и трябва) да бъде поставен директно след оператора INSERT, така че всичко се прави в едно и също извикване на база данни.

Пример:

mydb.ExecuteSql("INSERT INTO table(foreign_key1, value) VALUES(9, 'text'); SELECT SCOPE_IDENTITY();");

Можете да използвате OUTPUT, но има някои ограничения, които трябва да знаете:

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

person richardtallent    schedule 10.06.2009
comment
Невероятен. Нямах представа, че мога да комбинирам такива изказвания. Умен, нестандартен, отвратителен, полезен ... всички тези прилагателни идват на ум. :) - person skiphoppy; 10.06.2009
comment
Може да се направи в един оператор в SQL Server 2005 с OUTPUT - person gbn; 10.06.2009

SELECT SCOPE_IDENTITY()

Редактиране: Играя...

Ако само клаузата OUTPUT поддържа локални променливи.

Както и да е, за да получите диапазон от идентификатори, а не един единствен

DECLARE @Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))

INSERT @Mytable (valuecol) 
OUTPUT Inserted.keycol
SELECT 'harry'
UNION ALL
SELECT 'dick'
UNION ALL
SELECT 'tom'

Редактиране 2: В едно обаждане. Никога не съм имал случай да използвам тази конструкция.

DECLARE @Mytable TABLE (keycol int IDENTITY (1, 1), valuecol varchar(50))

INSERT @Mytable (valuecol) 
OUTPUT Inserted.keycol
VALUES('foobar')
person gbn    schedule 10.06.2009
comment
Подкрепям това. SCOPE_IDENTITY() връща най-новата самоличност в рамките на обхвата на последната ви заявка. Други методи @@IDENTITY и IDENT_CURRENT() не са ограничени до конкретен обхват - person James Conigliaro; 10.06.2009

В допълнение към @@IDENTITY, трябва да разгледате и SCOPE_IDENTITY() и IDENT_CURRENT(). Най-вероятно искате SCOPE_IDENTITY(). @@IDENTITY има проблем, тъй като може да върне стойност за самоличност, създадена в тригер на действителната таблица, която се опитвате да проследите.

Освен това това са функции с една стойност. Не знам как работи ключовата дума RETURNING на Oracle.

person Tom H    schedule 10.06.2009

SCOPE_IDENTITY

person Ken Burkhardt    schedule 10.06.2009

Зависи от контекста на вашето обаждане.

Ако извиквате това от клиентски код, можете да използвате OUTPUT и след това да прочетете върнатата стойност.

DECLARE @t TABLE (ColID int IDENTITY, ColStr varchar(20))

INSERT INTO @t (ColStr)
OUTPUT Inserted.ColID
VALUES ('Hello World')

Резултат:

      ColID
-----------
          1

Ако опаковате това в съхранена процедура, използването на OUTPUT е повече работа. Там ще искате да използвате SCOPE_IDENTITY(), но не можете да го направите в един израз. Разбира се, можете да поставите няколко израза на един ред с ';' разделител, но това не е едно твърдение.

DECLARE @idValue    int
DECLARE @t TABLE (ColID int IDENTITY, ColStr varchar(20))

INSERT INTO @t (ColStr) VALUES ('Hello World')

SELECT @idValue = SCOPE_IDENTITY()

Резултат: Променливата @idValue съдържа стойност за идентичност. Използвайте параметър OUTPUT, за да върнете стойността.

person Rob Garrison    schedule 10.06.2009

Можете да използвате OUTPUT INTO, което има допълнителните предимства да можете за улавяне на вмъкнати множество самоличности.

person Cade Roux    schedule 10.06.2009

INSERT INTO table(foreign_key1, value)VALUES(9, 'text');SELECT @@IDENTITY;

person Bhaskar    schedule 10.06.2009