Как я могу получить идентификаторы строк, которые были вставлены через insert ... select? - PullRequest
4 голосов
/ 22 февраля 2009

Я вставляю записи через запрос, подобный этому:

insert into tbl_xyz select field1 from tbl_abc

Теперь я хотел бы получить вновь сгенерированные значения IDENTITY вставленных записей. Как мне сделать это с минимальным количеством блокировок и максимальной надежностью?

Ответы [ 4 ]

19 голосов
/ 22 февраля 2009

Вы можете получить эту информацию, используя предложение OUTPUT .

Вы можете вывести свою информацию во временную целевую таблицу или представление.

Вот пример:

DECLARE @InsertedIDs TABLE (ID bigint)
INSERT into DestTable (col1, col2, col3, col4)
OUTPUT INSERTED.ID INTO @InsertedIDs
SELECT col1, col2, col3, col4 FROM SourceTable

Затем вы можете запросить в таблице InsertedID идентификаторы для ваших вставленных идентификаторов.

2 голосов
/ 22 февраля 2009

@@ IDENTITY вернет вам последнее введенное значение IDENTITY, поэтому у вас есть две возможные проблемы

  1. Остерегайтесь триггеров, выполняемых при вставке в table_xyz, поскольку это может изменить значение @@ IDENTITY.

  2. Имеет ли tbl_abc более одной строки. Если это так, то @@ IDENTITY будет возвращать только значение идентификатора последней строки

Проблема 1 может быть решена с помощью SCOPE__IDENTITY () вместо @@ IDENTITY Проблема 2 труднее решить. Определяет ли field1 в tbl_abc уникальную запись в tbl_xyz, если вы можете повторно выбрать данные из table_xyz с помощью столбца идентификаторов. Существуют и другие решения, использующие CURSORS, но они будут медленными.

1 голос
/ 22 февраля 2009

Насколько я знаю, вы не можете сделать это с прямым SQL в одном скрипте. Но вы можете создать триггер INSERT. Теперь я ненавижу срабатывает, но это один из способов сделать это.

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

Вы также можете заблокировать таблицу, получить ключ max, вставить строки, а затем снова получить ключ max и выполнить диапазон.

Trigger:

--Use the Inserted table.  This conaints all of the inserted rows.
SELECT * FROM Inserted

Temp Table:

insert field1, unique_col into #temp from tbl_abc

insert into tbl_xyz (field1, unique_col) select field1, unique_col from tbl_abc

--This could be an update, or a cursor, or whatever you want to do
SELECT * FROM tbl_xyz WHERE EXISTS (SELECT top 1 unique_col FROM #temp WHERE unique_col = tbl_xyz.unique_col)

Диапазон ключей:

Declare @minkey as int, @maxkey as int

BEGIN TRANS --You have to lock the table for this to work

  --key is the name of your identity column
  SELECT @minkey = MAX(key) FROM tbl_xyz
  insert into tbl_xyz select field1 from tbl_abc
  SELECT @maxkey = MAX(key) FROM tbl_xyz

COMMIT Trans

SELECT * FROM tbl_xyz WHERE key BETWEEN @minkey and @maxkey
1 голос
/ 22 февраля 2009
SELECT @@IDENTITY

Вот как я это делал раньше. Не уверен, что это будет соответствовать второй половине вашего поста.

EDIT
Нашел эту ссылку тоже, но не уверен, что она такая же ...
Как вставить несколько записей и получить значение идентификатора?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...