Лучший способ получить идентичность вставленной строки?

sql sql-server tsql

724209 просмотра

13 ответа

Каков наилучший способ получить IDENTITYвставленный ряд?

Я знаю , о @@IDENTITYи IDENT_CURRENTи , SCOPE_IDENTITYно не понимаю , плюсы и минусы , присоединенные к каждому.

Может кто-нибудь объяснить, пожалуйста, различия и когда я должен использовать каждый?

Автор: Oded Источник Размещён: 17.05.2019 02:46

Ответы (13)


1256 плюса

Решение
  • @@IDENTITYвозвращает последнее значение идентификатора, сгенерированное для любой таблицы в текущем сеансе, во всех областях. Вы должны быть осторожны здесь , так как это выходит за рамки. Вы можете получить значение из триггера вместо текущего оператора.

  • SCOPE_IDENTITY()возвращает последнее значение идентификатора, сгенерированное для любой таблицы в текущем сеансе и текущей области. Вообще то, что вы хотите использовать .

  • IDENT_CURRENT('tableName')возвращает последнее значение идентификатора, сгенерированное для конкретной таблицы в любом сеансе и любой области видимости. Это позволяет вам указать, из какой таблицы вы хотите получить значение, в случае, если два приведенных выше не совсем то, что вам нужно ( очень редко ). Кроме того, как заметил @ Гай Старбак : «Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не вставили запись».

  • OUTPUTПоложение о INSERTзаявлении позволит вам получить доступ к каждой строке , который был вставлен с помощью этого заявления. Поскольку он ограничен конкретным оператором, он более прост, чем другие функции выше. Однако, это немного более многословно (вам нужно вставить в таблицу переменную / временную таблицу, а затем запросить это), и это дает результаты даже в случае ошибки, когда оператор откатывается. Тем не менее, если в вашем запросе используется план параллельного выполнения, это единственный гарантированный метод получения идентификатора (за исключением отключения параллелизма). Однако он выполняется перед триггерами и не может использоваться для возврата сгенерированных триггером значений.

Автор: bdukes Размещён: 03.09.2008 09:38

161 плюса

Я считаю, что самый безопасный и точный метод получения вставленного идентификатора будет использовать предложение вывода.

например (взято из следующей статьи MSDN )

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate 
FROM Production.ScrapReason;
GO
Автор: Orry Размещён: 20.05.2011 02:43

101 плюса

Я говорю то же самое, что и другие парни, так что все правы, я просто пытаюсь прояснить это.

@@IDENTITYвозвращает идентификатор последней вещи, которая была вставлена ​​подключением вашего клиента к базе данных.
В большинстве случаев это работает нормально, но иногда запускается триггер и вставляется новая строка, о которой вы не знаете, и вы получаете идентификатор из этой новой строки вместо той, которую вы хотите

SCOPE_IDENTITY()решает эту проблему. Он возвращает идентификатор последней вещи, которую вы вставили в код SQL, который вы отправили в базу данных. Если триггеры идут и создают дополнительные строки, они не приведут к возвращению неверного значения. Ура

IDENT_CURRENTвозвращает последний идентификатор, который был вставлен кем-либо. Если какое-то другое приложение вставит еще одну строку в несчастное время, вы получите идентификатор этой строки вместо своей.

Если вы хотите быть осторожным, всегда используйте SCOPE_IDENTITY(). Если вы будете придерживаться @@IDENTITYи кто-то решит добавить триггер позже, весь ваш код сломается.

Автор: Orion Edwards Размещён: 03.09.2008 09:44

61 плюса

Лучший (читай: самый безопасный) способ получения идентификатора вновь вставленной строки - использование outputпредложения:

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)
Автор: Ian Kemp Размещён: 29.04.2013 07:22

21 плюса

добавлять

SELECT CAST(scope_identity() AS int);

в конце вашего оператора вставки SQL, затем

NewId = command.ExecuteScalar()

получит это.

Автор: Jim Размещён: 30.03.2015 06:25

14 плюса

MSDN

@@ IDENTITY, SCOPE_IDENTITY и IDENT_CURRENT - аналогичные функции в том, что они возвращают последнее значение, вставленное в столбец IDENTITY таблицы.

@@ IDENTITY и SCOPE_IDENTITY будут возвращать последнее значение идентификатора, сгенерированное в любой таблице в текущем сеансе. Однако SCOPE_IDENTITY возвращает значение только в текущей области; @@ IDENTITY не ограничивается конкретной областью применения.

IDENT_CURRENT не ограничен областью действия и сессией; он ограничен указанной таблицей. IDENT_CURRENT возвращает значение идентификатора, созданное для конкретной таблицы в любом сеансе и любой области. Для получения дополнительной информации см. IDENT_CURRENT.

  • IDENT_CURRENT - это функция, которая принимает таблицу в качестве аргумента.
  • @@ IDENTITY может дать неверный результат, если у вас есть триггер на столе
  • SCOPE_IDENTITY - ваш герой большую часть времени.
Автор: Jakub Šturc Размещён: 03.09.2008 09:37

13 плюса

Когда вы используете Entity Framework, он внутренне использует OUTPUTтехнику для возврата вновь вставленного значения идентификатора.

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');

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

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

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

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

Этот метод ( OUTPUT) доступен только в SQL Server 2008 или новее.

Автор: Ian Boyd Размещён: 04.11.2016 03:05

13 плюса

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

SCOPE_IDENTITY - это последний идентификатор, вставленный с использованием текущего соединения SQL, и в текущей области, то есть, если после вставки была вставлена ​​вторая IDENTITY, основанная на триггере, она не будет отражена в SCOPE_IDENTITY, а только выполненная вами вставка. , Честно говоря, у меня никогда не было причин использовать это.

IDENT_CURRENT (имя таблицы) является последней вставленной идентификацией независимо от соединения или области действия. Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не вставили запись.

Автор: Guy Starbuck Размещён: 03.09.2008 09:42

9 плюса

Я не могу говорить с другими версиями SQL Server, но в 2012 году вывод напрямую работает просто отлично. Вам не нужно беспокоиться о временном столе.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

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

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

Выход

ID
2
3
4
Автор: MarredCheese Размещён: 06.06.2018 04:58

8 плюса

ВСЕГДА используйте scope_identity (), НИКОГДА больше не нужно ничего.

Автор: erikkallen Размещён: 09.10.2009 08:35

0 плюса

После вашей вставки вы должны добавить это. И убедитесь, что имя таблицы, куда вставляются данные. Вы получите текущую строку, а не строку, на которую сейчас влияет оператор вставки.

IDENT_CURRENT('tableName')
Автор: Khan Ataur Rahman Размещён: 31.12.2017 06:04

0 плюса

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

$last = mysql_insert_id();
Автор: Sparky Размещён: 04.01.2019 06:49

0 плюса

Создайте uuidи вставьте его в столбец. Тогда вы можете легко идентифицировать вашу строку с помощью uuid.

Автор: Frank Roth Размещён: 13.03.2019 12:55
32x32