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

StackOverflow https://stackoverflow.com/questions/42648

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

  • IDENT_CURRENT('tableName') возвращает последнее идентификационное значение, сгенерированное для определенной таблицы в любом сеансе и любой области.Это позволяет вам указать, из какой таблицы вы хотите получить значение, на случай, если две вышеперечисленные таблицы не совсем то, что вам нужно (очень редкий).Кроме того, поскольку @Гай Старбак упоминалось: "Вы могли бы использовать это, если хотите получить текущее значение ИДЕНТИФИКАТОРА для таблицы, в которую вы не вставили запись".

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

Другие советы

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

например (взято из следующего 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

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

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

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

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

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

Лучший (читать:самый безопасный) способ получить идентификатор вновь вставленной строки - это использовать 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)

Добавить

SELECT CAST(scope_identity() AS int);

до конца вашего оператора insert sql, затем

NewId = command.ExecuteScalar()

я верну его.

MSDN

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

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

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

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

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 или новее.

@@ИДЕНТИФИКАЦИЯ является последним идентификатором, вставленным с использованием текущего SQL-соединения.Это хорошее значение для возврата из хранимой процедуры insert, где вам просто нужно вставить идентификатор для вашей новой записи, и вам все равно, были ли добавлены дополнительные строки позже.

SCOPE_IDENTITY ОБЛАСТЬ ДЕЙСТВИЯ вставлено ли последнее удостоверение с использованием текущего SQL-соединения и в текущей области видимости - то есть, если бы после вашей вставки было вставлено второе удостоверение на основе триггера, оно не было бы отражено в SCOPE_IDENTITY, только выполненная вами вставка.Честно говоря, у меня никогда не было причин использовать это.

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

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

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

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

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

Выходной сигнал

ID
2
3
4

ВСЕГДА используйте scope_identity(), в чем-либо другом никогда не будет необходимости.

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

IDENT_CURRENT('tableName')

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

$last = mysql_insert_id();

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top