Как избежать: «SQL Server автоматически использует новое вставленное значение в качестве текущего значения идентификатора». - PullRequest
1 голос
/ 18 января 2011

Я использую SQL Server 2008

согласно Microsoft, http://msdn.microsoft.com/en-us/library/ms188059.aspx

, когда я выполняю следующее

set identity_insert on  
//insert statements here
set identity_insert off

, установлен идентификатор столбцадо максимального значения.Могу ли я избежать этого?

Рассмотрим следующий сценарий:

моя таблица имеет 2 строки следующим образом

id, name  comm  
1,  John, 232.43  
2,  Alex, 353.52  

, теперь используя вышеуказанный код, когда я вставляю

10, Smith, 334.23

согласно приведенной выше ссылке, SQL Server автоматически устанавливает идентичность на 10. Таким образом, для вновь вставленных записей (без использования identity_insert) идентификатор автоматически начинается с 11.

Я хочу значение идентификаторабыть 3, после использования identity_insert

, пожалуйста, помогите.

Ответы [ 4 ]

3 голосов
/ 18 января 2011

Вот тестовая таблица для этого обсуждения

create table t4721736 ( id int identity primary key, name varchar(10), comm money )
insert t4721736 select 'John', 232.43 -- id=1
insert t4721736 select 'Alex', 353.52 -- id=2

-- check contents    
select * from t4721736 

-- do all this in a transaction
BEGIN TRAN

-- dummy insert
insert t4721736 select 'dummy', null

-- get what the id should be
declare @resetto bigint
set @resetto = scope_identity()

-- remove dummy record
delete t4721736 where id = @resetto

-- perform the insert(s)
set identity_insert t4721736 on;
insert t4721736(id,name,comm) select 10000000, 'Smith', 334.23;
set identity_insert t4721736 off;

-- reset the identity
set @resetto = @resetto - 1  -- it needs to be 1 prior
DBCC CHECKIDENT(t4721736, RESEED, @resetto)

COMMIT

Предполагая, что вы полностью понимаете (я полагаю, что да), что произойдет сбой, как только диапазон достигнет записей с назначенными идентификаторами. SQL Server не выполняет автоматического пропуска идентификаторов, к которым уже прикреплены записи.

это не будет проблемой, потому что когда я вставить с помощью identity_insert, значение идентификатор будет больше, чем 10 миллионов. так что не будет никаких проблем сталкиваясь

Чтобы увидеть, как это не сработает, сократите процесс, изменив «10000000» на «10» в приведенном выше коде. Затем выполните следующие действия:

-- inspect contents, shows records 1,2,10
select * from t4721736

-- next, insert 7 more records, bringing the id up to 9
insert t4721736 select 'U3', 0
insert t4721736 select 'U4', 0
insert t4721736 select 'U5', 0
insert t4721736 select 'U6', 0
insert t4721736 select 'U7', 0
insert t4721736 select 'U8', 0
insert t4721736 select 'U9', 0

Наконец, попробуйте следующую вставку ниже

insert t4721736 select 'U10', 0
2 голосов
/ 18 января 2011

Если эти строки, которые вы вставляете, являются специальными / магическими строками (поэтому им нужны определенные идентификаторы), рассматривали ли вы вопрос о том, чтобы эти строки имели отрицательные значения идентификаторов?Таким образом, нет конфликта, и значение IDENTITY не будет сброшено при добавлении их.

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

2 голосов
/ 18 января 2011

Вы можете сбросить начальное значение, используя DBCC CHECKIDENT:

DBCC CHECKIDENT ("MyTable", RESEED, 3);
GO

Однако вы вставили идентификатор записи 10 , так что да,следующим действительно будет 11.

Это задокументировано в команде:

Если текущее значение идентификатора для таблицы меньше максимального значения идентификатора, хранящегося в столбце идентификаторов,оно сбрасывается с использованием максимального значения в столбце идентификаторов.

Вы не можете использовать его обоими способами.Либо самый низкий идентификатор будет значением базового семени, либо нет.

0 голосов
/ 19 января 2011

Еще один способ обойти дилемму «засаженного жука» - это создать собственную процедуру создания идентификатора и таблицу отслеживания. Таблица содержит имя таблицы и значение, которым должен быть следующий идентификатор. Таким образом, вы можете сбросить любое значение в любое время. Процедура будет включать логику, чтобы проверить, существует ли следующий сгенерированный ключ, и если он существует, он будет увеличивать ключ до тех пор, пока не найдет идентификатор, который не существует в таблице, и передаст его вам. Это должно быть реализовано на всех вставках, чтобы работать правильно. Что возможно с помощью триггера. Недостатком является больше затрат на обработку, чем использование отрицательного числа, как предлагает Damien_The_Unbeliever.

...