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



что является лучшим способом, чтобы получить IDENTITY вставить строку?



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



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

510   11  

11 ответов:

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

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

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

  • The 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 возвращает последний ID, который был вставлен кем-либо. Если какое-то другое приложение случайно вставит другую строку в неурегулированное время, вы получите идентификатор этой строки вместо вашего.

если вы хотите играть в нее безопасно, всегда используйте 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 и SCOPE_IDENTITY вернут последнее значение идентификатора, сгенерированное в любой таблице в текущем сеансе. Однако SCOPE_IDENTITY возвращает значение только в пределах текущей области; @@IDENTITY не ограничивается определенной областью.

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

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

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

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

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

когда вы используете 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 или более поздней версии.

всегда используйте scope_identity (), там никогда не нужно ничего другого.

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

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

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

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

выход

ID
2
3
4

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

IDENT_CURRENT('tableName')

Comments

    Ничего не найдено.