Лучший способ получить личность вставленной строки?
Каков наилучший способ получить IDENTITY
вставленной строки?
Я знаю о @@IDENTITY
и IDENT_CURRENT
и SCOPE_IDENTITY
, но не понимаю плюсы и минусы, связанные с каждым.
Может кто-нибудь объяснит различия и когда я буду использовать их?
Ответы
Ответ 1
-
@@IDENTITY
возвращает последнее значение идентификации, сгенерированное для любой таблицы текущего сеанса, во всех областях. Вам нужно быть осторожным здесь, так как он доступен в разных областях. Вы можете получить значение из триггера вместо текущего оператора.
-
SCOPE_IDENTITY()
возвращает последнее значение идентификации, сгенерированное для любой таблицы текущего сеанса и текущей области. Как правило, вы хотите использовать.
-
IDENT_CURRENT('tableName')
возвращает последнее значение идентификации, сгенерированное для конкретной таблицы в любом сеансе и в любой области. Это позволяет указать, из какой таблицы вы хотите получить значение, в случае, если два выше не совсем то, что вам нужно (очень редко). Кроме того, как сказал @Guy Starbuck, вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не ввели запись."
-
Предложение OUTPUT
оператора INSERT
позволит вам получить доступ к каждой строке, вставленной через этот оператор. Поскольку он привязан к конкретному утверждению, он более простой, чем другие функции выше. Тем не менее, он немного более подробный (вам нужно будет вставить в таблицу table/temp table, а затем запросить это), и он дает результаты даже в сценарии ошибок, когда инструкция откат. Тем не менее, если ваш запрос использует параллельный план выполнения, это только гарантированный метод для получения идентификатора (без отключения parallelism). Тем не менее, он выполняется перед триггерами и не может использоваться для возврата генерируемых триггером значений.
Ответ 2
Я считаю, что самый безопасный и самый точный метод извлечения вставленного 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
Ответ 3
Я говорю то же самое, что и другие ребята, поэтому все правильно, я просто пытаюсь сделать это более понятным.
@@IDENTITY
возвращает идентификатор последней вещи, которая была вставлена вашим клиентским соединением в базу данных.
В большинстве случаев это работает нормально, но иногда срабатывает триггер и вставляет новую строку, о которой вы не знаете, и вы получите идентификатор из этой новой строки, а не тот, который вы хотите
SCOPE_IDENTITY()
решает эту проблему. Он возвращает идентификатор последней вещи, которую вы вставили в код SQL, который вы отправили в базу данных. Если триггеры идут и создают дополнительные строки, они не будут возвращать неправильное значение. Hooray
IDENT_CURRENT
возвращает последний идентификатор, который был вставлен кем-либо. Если какое-либо другое приложение случайно введет другую строку в нерабочее время, вы получите идентификатор этой строки, а не ваш.
Если вы хотите играть в нее безопасно, всегда используйте SCOPE_IDENTITY()
. Если вы придерживаетесь @@IDENTITY
, и кто-то решает добавить триггер позже, весь ваш код сломается.
Ответ 4
Самый лучший (читаемый: самый безопасный) способ получить личность вновь вставленной строки - это использовать предложение 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)
Ответ 5
Добавить
SELECT CAST(scope_identity() AS int);
до конца вашего встраиваемого sql-оператора, затем
NewId = command.ExecuteScalar()
получит его.
Ответ 6
Когда вы используете 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 или новее.
Ответ 7
MSDN
@@IDENTITY, SCOPE_IDENTITY и IDENT_CURRENT являются схожими функциями, поскольку они возвращают последнее значение, вставленное в столбец IDENTITY таблицы.
@@IDENTITY и SCOPE_IDENTITY вернут последнее значение идентификации, сгенерированное в любой таблице текущего сеанса. Однако SCOPE_IDENTITY возвращает значение только в пределах текущей области; @@IDENTITY не ограничивается определенной областью.
IDENT_CURRENT не ограничивается областью и сеансом; он ограничен указанной таблицей. IDENT_CURRENT возвращает значение идентификатора, сгенерированное для конкретной таблицы, в любом сеансе и в любой области. Для получения дополнительной информации см. IDENT_CURRENT.
- IDENT_CURRENT - это функция, которая принимает таблицу в качестве аргумента.
- @@IDENTITY может возвращать запутанный результат, когда у вас есть триггер в таблице
- SCOPE_IDENTITY - ваш герой большую часть времени.
Ответ 8
@@IDENTITY - это последняя идентификация, вставленная с использованием текущего соединения SQL. Это хорошее значение для возврата из хранимой процедуры вставки, где вам просто нужна идентификация, вставленная для вашей новой записи, и не волнует, что после этого добавлено больше строк.
SCOPE_IDENTITY - это последняя идентификация, вставленная с использованием текущего SQL-соединения, и в текущей области - то есть, если вторая вставка была вставлена на основе триггера после вашей вставки, будет отображаться в SCOPE_IDENTITY, только вставку, которую вы выполнили. Честно говоря, у меня никогда не было причины использовать это.
IDENT_CURRENT (имя_таблицы) - это последняя идентификация, вставленная независимо от соединения или области видимости. Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не ввели запись.
Ответ 9
Я не могу говорить с другими версиями SQL Server, но в 2012 году вывод напрямую работает просто отлично. Вам не нужно беспокоиться о временной таблице.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)
Кстати, этот метод также работает при вставке нескольких строк.
INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
(...),
(...),
(...)
Выход
ID
2
3
4
Ответ 10
ВСЕГДА используйте scope_identity(), НИКОГДА ничего не нужно.
Ответ 11
Создайте uuid
и вставьте его в столбец. Тогда вы можете легко идентифицировать вашу строку с помощью uuid. Это единственное 100% рабочее решение, которое вы можете реализовать. Все остальные решения слишком сложны или не работают в тех же самых крайних случаях.
Ответ 12
После вашего заявления о вставки вам нужно добавить это. И Удостоверьтесь в имени таблицы, где данные вставляются. Вы получите текущую строку, где строка, затронутая только теперь вашим оператором insert.
IDENT_CURRENT('tableName')
Ответ 13
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);
Ответ 14
Если вы ищете последний добавленный/обновленный идентификатор, это может быть немного старомодно, но есть много людей, использующих более старый PHP, Pre 5.5, если быть более точным. Более подробную информацию можно найти на http://php.net/manual/en/function.mysql-insert-id.php
$last = mysql_insert_id();