Каков наилучший способ получить IDENTITY
вставленный ряд?
Я знаю , о @@IDENTITY
и IDENT_CURRENT
и , SCOPE_IDENTITY
но не понимаю , плюсы и минусы , присоединенные к каждому.
Может кто-нибудь объяснить, пожалуйста, различия и когда я должен использовать каждый?
sql
sql-server
tsql
Одед
источник
источник
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)
или более старый метод:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
вы можете получить его в c #, используя ExecuteScalar ().OUTPUT
предложению в SQL Server.Ответы:
@@IDENTITY
возвращает последнее значение идентификатора, сгенерированное для любой таблицы в текущем сеансе, во всех областях. Вы должны быть осторожны здесь , так как это выходит за рамки. Вы можете получить значение из триггера вместо текущего оператора.SCOPE_IDENTITY()
возвращает последнее значение идентификатора, сгенерированное для любой таблицы в текущем сеансе и текущей области. Вообще то, что вы хотите использовать .IDENT_CURRENT('tableName')
возвращает последнее значение идентификатора, сгенерированное для конкретной таблицы в любом сеансе и любой области видимости. Это позволяет вам указать, из какой таблицы вы хотите получить значение, в случае, если два приведенных выше не совсем то, что вам нужно ( очень редко ). Кроме того, как заметил @ Гай Старбак : «Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не вставили запись».OUTPUT
Положение оINSERT
заявлении позволит вам получить доступ к каждой строке , который был вставлен с помощью этого заявления. Поскольку он ограничен конкретным оператором, он более прост, чем другие функции выше. Однако это немного более многословно (вам нужно вставить в таблицу переменную / временную таблицу, а затем запросить ее), и это дает результаты даже в случае ошибки, когда оператор откатывается. Тем не менее, если в вашем запросе используется план параллельного выполнения, это единственный гарантированный метод получения идентификатора (за исключением отключения параллелизма). Однако он выполняется перед триггерами и не может использоваться для возврата сгенерированных триггером значений.источник
output
вам не нужно создавать временную таблицу для хранения и запроса результатов. Просто оставьтеinto
часть предложения output, и он выведет их в набор результатов.OUTPUT
является «лучшей», если вы не используете триггеры и обрабатываете ошибки, ноSCOPE_IDENTITY
является самой простой и очень редко имеет проблемыЯ считаю, что самый безопасный и точный метод получения вставленного идентификатора будет использовать предложение вывода.
например (взято из следующей статьи MSDN )
источник
OUTPUT
, так что похоже, что это просто SQL Server 2000 и более ранниеЯ говорю то же самое, что и другие парни, так что все правы, я просто пытаюсь прояснить это.
@@IDENTITY
возвращает идентификатор последней вещи, которая была вставлена подключением вашего клиента к базе данных.В большинстве случаев это работает нормально, но иногда запускается триггер и вставляется новая строка, о которой вы не знаете, и вы получаете идентификатор из этой новой строки вместо той, которую вы хотите
SCOPE_IDENTITY()
решает эту проблему. Он возвращает идентификатор последней вещи, которую вы вставили в код SQL , отправленный в базу данных. Если триггеры идут и создают дополнительные строки, они не приведут к возвращению неправильного значения. УраIDENT_CURRENT
возвращает последний идентификатор, который был вставлен кем-либо. Если какое-то другое приложение вставит еще одну строку в несчастное время, вы получите идентификатор этой строки вместо вашей.Если вы хотите быть осторожным, всегда используйте
SCOPE_IDENTITY()
. Если вы будете придерживаться@@IDENTITY
и кто-то решит добавить триггер позже, весь ваш код сломается.источник
Лучший (читай: самый безопасный) способ получения идентификатора вновь вставленной строки - использовать
output
предложение:источник
scope_identity()
любом случае, очень редко для вставок в одну строку (наиболее распространенный случай ) можно получить параллельные планы. И эта ошибка была исправлена более чем за год до этого ответа.output
вместо использованияscope_identity()
. Я удалил FUD о кластеризации в ответе.Добавить
в конце вашего оператора вставки SQL, затем
получит это.
источник
Когда вы используете Entity Framework, он внутренне использует
OUTPUT
технику для возврата вновь вставленного значения идентификатора.Выходные результаты сохраняются во временной табличной переменной, присоединяются обратно к таблице и возвращают значение строки из таблицы.
Примечание: я понятия не имею, почему EF внутренне присоединяет эфемерную таблицу обратно к реальной таблице (при каких обстоятельствах эти две пары не совпадают).
Но это то, что делает EF.
Этот метод (
OUTPUT
) доступен только в SQL Server 2008 или новее.Редактировать - причина присоединения
Причина, по которой Entity Framework присоединяется к исходной таблице, а не просто использует
OUTPUT
значения, заключается в том, что EF также использует эту технику для полученияrowversion
новой вставленной строки.Вы можете использовать оптимистичный параллелизм в моделях вашей сущности, используя
Timestamp
атрибут: 🕗Когда вы сделаете это, Entity Framework потребуется
rowversion
только что вставленная строка:И для того, чтобы получить это,
Timetsamp
вы не можете использоватьOUTPUT
пункт.Это потому, что если на столе есть триггер, любой
Timestamp
ваш ВЫХОД будет неверным:Возвращенная временная метка никогда не будет правильной, если у вас есть триггер на столе. Поэтому вы должны использовать отдельный
SELECT
.И даже если вы захотите перенести неправильную версию строки, другая причина для выполнения отдельной процедуры
SELECT
состоит в том, что вы не можете ВЫХОДИТЬrowversion
в переменную таблицы:Третья причина сделать это для симметрии. При выполнении
UPDATE
таблицы с триггером вы не можете использоватьOUTPUT
предложение. Попытка сделатьUPDATE
сOUTPUT
не поддерживается, и даст ошибку:Единственный способ сделать это с последующим
SELECT
заявлением:источник
TurboEncabulators
:)MSDN
источник
@@ IDENTITY - это последний идентификатор, вставленный с использованием текущего соединения SQL. Это хорошее значение для возврата из хранимой процедуры вставки, где вам просто нужно вставить идентификатор для вашей новой записи, и не волнует, будет ли добавлено больше строк после этого.
SCOPE_IDENTITY - это последний идентификатор, вставленный с использованием текущего соединения SQL, и в текущей области - то есть, если после вставки была вставлена вторая IDENTITY, основанная на триггере, она не будет отражена в SCOPE_IDENTITY, только выполненная вами вставка , Честно говоря, у меня никогда не было причин использовать это.
IDENT_CURRENT (имя таблицы) является последним идентификатором, вставленным независимо от соединения или области действия. Вы можете использовать это, если хотите получить текущее значение IDENTITY для таблицы, в которую вы не вставили запись.
источник
Я не могу говорить с другими версиями SQL Server, но в 2012 году вывод напрямую работает просто отлично. Вам не нужно беспокоиться о временном столе.
Кстати, эта техника также работает при вставке нескольких строк.
Вывод
источник
OUTPUT
. Если вам не нужна временная таблица, тогда ваш запрос окажется намного проще.ВСЕГДА используйте scope_identity (), НИКОГДА больше не нужно ничего.
источник
Создайте
uuid
и вставьте его в столбец. Тогда вы можете легко идентифицировать вашу строку с помощью uuid. Это единственное 100% рабочее решение, которое вы можете реализовать. Все остальные решения слишком сложны или не работают в тех же самых крайних случаях. Например:1) Создать строку
2) Получить созданный ряд
источник
uuid
базы данных. Так что ряд будет найден быстрее.https://www.npmjs.com/package/uuid
.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()
Еще один способ гарантировать идентичность вставляемых строк - указать значения идентификаторов и использовать
SET IDENTITY_INSERT ON
иOFF
. Это гарантирует, что вы точно знаете, что такое значения идентичности! Пока значения не используются, вы можете вставить эти значения в столбец идентификаторов.Это может быть очень полезным методом, если вы загружаете данные из другого источника или объединяете данные из двух баз данных и т. Д.
источник
Несмотря на то, что это старый поток, существует более новый способ сделать это, который позволяет избежать некоторых ошибок в столбце IDENTITY в более старых версиях SQL Server, таких как разрывы в значениях идентификаторов после перезагрузки сервера . Последовательности доступны в SQL Server 2016 и более поздних версиях. Более новый способ заключается в создании объекта SEQUENCE с использованием TSQL. Это позволяет создавать собственный объект числовой последовательности в SQL Server и контролировать его приращение.
Вот пример:
Затем в TSQL вы должны сделать следующее, чтобы получить следующий идентификатор последовательности:
Вот ссылки на CREATE SEQUENCE и NEXT VALUE FOR
источник
После вашей вставки вы должны добавить это. И убедитесь, что имя таблицы, куда вставляются данные. Вы получите текущую строку, а не строку, на которую сейчас влияет оператор вставки.
источник