2016-03-20 3 views
0

У меня есть таблица с этой структурой:SQL Server - Порядок идентификации полей в таблице

CREATE TABLE [dbo].[cl](
[ID] [int] IDENTITY(1,1) NOT NULL, 
[NIF] [numeric](9, 0) NOT NULL, 
[Name] [varchar](80) NOT NULL, 
[Address] [varchar](100) NULL, 
[City] [varchar](40) NULL, 
[State] [varchar](30) NULL, 
[Country] [varchar](25) NULL, 
Primary Key([ID],[NIF]) 
); 

Представьте себе, что эта таблица имеет 3 записей. Запись 1, 2, 3 ... Когда я удаляю Record number 2, поле IDENTITY генерирует Gap. Затем таблица имеет запись 1 и запись 3. Ее не правильно!

Даже если я использую:

DBCC CHECKIDENT('cl', RESEED, 0) 

Это не решает мою проблему becuase будет установить идентификатор следующего вставленной записи 1. И это не исправить либо потому, что таблица будет иметь несколько ID ,

Кто-нибудь знает об этом?

+0

Разрыв, который вам не нравится, есть специально. Это явный признак того, что есть что-то, перед чем сейчас отсутствует. Представьте, что в таблице содержатся финансовые транзакции, и кто-то совершает несанкционированную транзакцию и пытался скрыть ее, удалив ее из таблицы.Затем вы можете сразу сказать, что одна транзакция отсутствует (которую вы можете потенциально восстановить из журнала аудита, резервных копий или из трасс. Если вы хотите постоянно записывать записи, то «identity (1,1)» не является тем, что вы ищете. – Ralph

+0

Представьте, если в таблице было 1 миллион записей, и вы удаляете запись 2. Вы не хотите, чтобы база данных меняла ключ для всех этих записей (и любых внешних ключей, указывающих на все эти записи). это стандартное поведение, к которому вам придётся привыкнуть, если вы хотите получить идентификатор. В противном случае вам придется создавать и использовать свои собственные ключи (и гарантировать их обманирование). –

+0

@Ralph У меня нет большого опыта работы с SQL Server. То, что я ищу, является полем AUTO_INCREMENT, как в MySQL, когда когда-либо я вставляю что-то, что он автоинкремент, а когда я удаляю, есть триггер, который всегда конфигурируется, чтобы «перестроить» поле «Auto increment». И это то, что я ищу в SQL. – rui404

ответ

3

Никакая база данных не собирается повторно или пересчитывать автоматически увеличивающееся поле/идентификатор, чтобы использовать значения между идентификаторами, как в вашем примере. Это непрактично на многих уровнях, но некоторые примеры могут быть:

  • Целостность - так как повторно используется идентификатор может означать записи в других системах, ссылаясь на старое значение, когда новое значение сохраняется
  • Производительность - пытаясь найти самый низкий зазор для каждого введенного значения

В MySQL это тоже не происходит (по крайней мере, в InnoDB или MyISAM - вы используете что-то другое?). В InnoDB поведение идентично SQL Server, где счетчик управляется за пределами таблицы, поэтому удаленные значения или откатные транзакции оставляют промежутки между последним значением и следующей вставкой. В MyISAM значение вычисляется во время ввода вместо управления через внешний счетчик. Этот расчет - это то, что дает восприятие того, что он пересчитывается - он просто никогда не вычисляется до фактической необходимости (MAX (Id) + 1). Даже это не будет вставлять внутренние промежутки (например, id = 2 в вашем примере).

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

Если вы настаиваете на использовании этих пробелов, самым быстрым методом будет удаление журналов в отдельной таблице, а затем использование триггера INSTEAD OF INSERT для выполнения вставок с вашими намеченными ключами, сначала поиск записей в таблице этих исключений повторное использование (затем удаление их для предотвращения повторного использования), а затем использование MAX (Id) + 1 для любых дополнительных строк для вставки.

-1

Я предполагаю, что вы хотите что-то вроде этого:

create table dbo.cl 
    (
    SurrogateKey int identity(1, 1) 
         primary key 
         not null, 
    ID int not null, 
    NIF numeric(9, 0) not null, 
    Name varchar(80) not null, 
    Address varchar(100) null, 
    City varchar(40) null, 
    State varchar(30) null, 
    Country varchar(25) null, 
    unique (ID, NIF) 
    ) 
go 

Я добавил суррогатный ключ, так что вы будете иметь лучшее из обоих миров. Теперь нужно просто триггер на столе, чтобы «настроить» идентификатор, когда некоторые до ID будет удален:

create trigger tr_on_cl_for_auto_increment on dbo.cl 
    after delete, update 
as 
    begin 
     update dbo.cl 
     set  ID = d.New_ID 
     from dbo.cl as c 
     inner join (
        select c2.SurrogateKey, 
          row_number() over (order by c2.SurrogateKey asc) as New_ID 
        from dbo.cl as c2 
        ) as d 
     on  c.SurrogateKey = d.SurrogateKey 
    end 
go 

Конечно, это решение также означает, что вы должны обеспечить (при вставке новой записи) что вы сами проверяете, какой идентификатор нужно вставить дальше.