Каков наилучший способ получить IDENTITY
вставленной строки?
Я знаю о @@IDENTITY
и IDENT_CURRENT
и SCOPE_IDENTITY
, но не понимаю плюсы и минусы, связанные с каждым.
Может кто-нибудь объяснит различия и когда я буду использовать их?
Каков наилучший способ получить IDENTITY
вставленной строки?
Я знаю о @@IDENTITY
и IDENT_CURRENT
и SCOPE_IDENTITY
, но не понимаю плюсы и минусы, связанные с каждым.
Может кто-нибудь объяснит различия и когда я буду использовать их?
@@IDENTITY
возвращает последнее значение идентификации, сгенерированное для любой таблицы текущего сеанса, во всех областях. Вам нужно быть осторожным здесь, так как он доступен в разных областях. Вы можете получить значение из триггера вместо текущего оператора.
SCOPE_IDENTITY()
возвращает последнее значение идентификации, сгенерированное для любой таблицы текущего сеанса и текущей области. Как правило, вы хотите использовать.
IDENT_CURRENT('tableName')
возвращает последнее значение идентификации, сгенерированное для конкретной таблицы в любом сеансе и в любой области. Это позволяет указать, из какой таблицы вы хотите получить значение, в случае, если два выше не совсем то, что вам нужно (очень редко). Кроме того, как сказал @Guy Starbuck, вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не ввели запись."
Я считаю, что самый безопасный и самый точный метод извлечения вставленного id будет использовать предложение вывода.
например (взято из следующей статьи 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, который вы отправили в базу данных. Если триггеры идут и создают дополнительные строки, они не будут возвращать неправильное значение. Hooray
IDENT_CURRENT
возвращает последний идентификатор, который был вставлен кем-либо. Если какое-либо другое приложение случайно введет другую строку в нерабочее время, вы получите идентификатор этой строки, а не ваш.
Если вы хотите играть в нее безопасно, всегда используйте SCOPE_IDENTITY()
. Если вы придерживаетесь @@IDENTITY
, и кто-то решает добавить триггер позже, весь ваш код сломается.
Самый лучший (читаемый: самый безопасный) способ получить личность вновь вставленной строки - это использовать предложение output
:
create table TableWithIdentity
( IdentityColumnName int identity(1, 1) not null primary key,
... )
-- type of this table 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);
до конца вашего встраиваемого sql-оператора, затем
NewId = command.ExecuteScalar()
получит его.
Когда вы используете 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 или новее.
@@IDENTITY, SCOPE_IDENTITY и IDENT_CURRENT являются схожими функциями, поскольку они возвращают последнее значение, вставленное в столбец IDENTITY таблицы.
@@IDENTITY и SCOPE_IDENTITY вернут последнее значение идентификации, сгенерированное в любой таблице текущего сеанса. Однако SCOPE_IDENTITY возвращает значение только в пределах текущей области; @@IDENTITY не ограничивается определенной областью.
IDENT_CURRENT не ограничивается областью и сеансом; он ограничен указанной таблицей. IDENT_CURRENT возвращает значение идентификатора, сгенерированное для конкретной таблицы, в любом сеансе и в любой области. Для получения дополнительной информации см. IDENT_CURRENT.
@@IDENTITY - это последняя идентификация, вставленная с использованием текущего соединения SQL. Это хорошее значение для возврата из хранимой процедуры вставки, где вам просто нужна идентификация, вставленная для вашей новой записи, и не волнует, что после этого добавлено больше строк.
SCOPE_IDENTITY - это последняя идентификация, вставленная с использованием текущего SQL-соединения, и в текущей области - то есть, если вторая вставка была вставлена на основе триггера после вашей вставки, будет отображаться в SCOPE_IDENTITY, только вставку, которую вы выполнили. Честно говоря, у меня никогда не было причины использовать это.
IDENT_CURRENT (имя_таблицы) - это последняя идентификация, вставленная независимо от соединения или области видимости. Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не ввели запись.
Я не могу говорить с другими версиями SQL Server, но в 2012 году вывод напрямую работает просто отлично. Вам не нужно беспокоиться о временной таблице.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)
Кстати, этот метод также работает при вставке нескольких строк.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
(...),
(...),
(...)
Выход
ID
2
3
4
ВСЕГДА используйте scope_identity(), НИКОГДА ничего не нужно.
Создайте uuid
и вставьте его в столбец. Тогда вы можете легко идентифицировать вашу строку с помощью uuid. Это единственное 100% рабочее решение, которое вы можете реализовать. Все остальные решения слишком сложны или не работают в тех же самых крайних случаях.
После вашего заявления о вставки вам нужно добавить это. И Удостоверьтесь в имени таблицы, где данные вставляются. Вы получите текущую строку, где строка, затронутая только теперь вашим оператором insert.
IDENT_CURRENT('tableName')
TL & DR: Создайте выходную переменную для размещения запроса на возвращение идентификатора. Это использовалось в Dotnet Core с PostGres. Я чувствую, что это может быть полезно для тех, кто не использует SQL.
Обоснование: оператор INSERT возвращает идентификатор, который можно получить только с помощью параметра OUTPUT. Смотрите ниже.
Цель состоит в том, чтобы получить ВЫХОД из "возвращающегося"
NpgsqlParameter idOut = new NpgsqlParameter
{
Direction = System.Data.ParameterDirection.Output
};
await _context.Database.ExecuteSqlCommandAsync($"INSERT INTO pulserelations (pulseid, create_time, modified_time) VALUES ({pulse_id}, now(),now()) RETURNING pulserelationid;", idOut);
Если вы ищете последний добавленный/обновленный идентификатор, это может быть немного старомодно, но есть много людей, использующих более старый PHP, Pre 5.5, если быть более точным. Более подробную информацию можно найти на http://php.net/manual/en/function.mysql-insert-id.php
$last = mysql_insert_id();