Чому видалення властивості Identity у стовпці не підтримується


11

Я читав, що після SQL Server 2000 можливість "від’єднати" стовпець ідентифікації була видалена. І що це був "За задумом" (не просто відсутня функція).

Ось приклад, який я знайшов у своєму блозі . Він включає оновлення системних таблиць. (І цю здатність було видалено після SQL Server 2000.) Я розумію, що робити це за допомогою системних таблиць не є хорошою ідеєю. Мені просто цікаво, чому особливості зробити це іншим способом не існує.

Якщо вирішити цю проблему, це призведе до значної роботи. (Скопіюйте багато сотень мільйонів рядків у нові таблиці в умовах нетерпимого простою.)

Тому я думав, що запитаю "Чому".

Що змінилося в Sql Server 2005 та пізніших версіях, що зробило це погано? Або завжди було погано, і просто не замкнули?

Яку "найкращу практику" (або подібний принцип) було б порушено, зробивши стовпець ідентичності знову нормальним стовпцем?

-

Оновлення, щоб відповісти на запит "чому я це роблю":
Це підсумок дуже високого рівня: я почну додавати розділи до своїх таблиць. (Щоб я міг архівувати / очищати старі дані.) Це все просто. Але мені періодично потрібно перемістити запис на інший розділ, щоб він не видалявся (коли розділ з'являється для архіву / видалення). (У мене стовпчик розбиття збільшується на 2, щоб завжди було місця для переміщення рядка на інший розділ.)

Але якщо стовпчик розділення - це стовпець ідентичності, тоді я повинен видалити та повторно вставити значення (немає можливості оновити значення стовпця ідентичності). Що спричиняє проблеми з тиражуванням.

Тому я хочу використовувати послідовність замість стовпця ідентичності. Але цей комутатор дуже великий на великих базах даних.

Відповіді:


22

По суті, ваше питання:

Чому я більше не можу займатися такою ризикованою справою, яку мені ніколи не слід було дозволити робити?

Відповідь на це питання значною мірою не має значення (хоча ви можете побачити деякі коментарі Microsoft у цих елементах Connect із запитом про цю функціональність: # 294193 та # 252226). Для повноти мій конспект такий: Можливість вилучити властивість ідентичності була навмисним побічним ефектом наявності в першу чергу здатності возитись із системними таблицями. Це не було призначене для використання багатьма способами, які це було, часто з дуже поганими наслідками, і таким чином його було усунено. Це був бездокументований, непідтримуваний, злом системної таблиці. Можливість змінювати дані в системних таблицях не була видалена, оскільки Microsoft більше не хотіла, щоб ви зламали вихід із стовпця, що був стовпцем ідентичності, його було видалено, оскільки спілкування із системними таблицями надзвичайно ризиковано. Видалення властивості IDENTITY саме по собі не було спеціально націленим видаленням функції, і я б ніколи повністю не довіряв цьому підходу, навіть у стародавні часи, коли це було можливо.

Це сказало, а як ми натомість відповімо на це запитання?

Як видалити властивість Ідентичність стовпця з мінімальним простоєм або без нього?

Це ви можете легко зробити, використовуючи ALTER TABLE ... SWITCHтехніку, я впевнений, що я вперше навчився у нашого Пола Уайта в обхідних шляхах для підключення №252226 . Короткий приклад, враховуючи цю просту таблицю:

CREATE TABLE dbo.Original
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  name SYSNAME
);
GO

INSERT dbo.Original(name) VALUES(N'foo'),(N'bar');
GO

SELECT * FROM dbo.Original;
GO

Результати:

ID  name
--  ----
1   foo
2   bar

Тепер створимо тіньову таблицю та переключимось на неї, а потім скиньмо стару таблицю, перейменуємо нову та відновимо звичайну діяльність:

CREATE TABLE dbo.New
(
  ID INT PRIMARY KEY,
  name SYSNAME
);
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
  ALTER TABLE dbo.Original SWITCH TO dbo.New;
  DROP TABLE dbo.Original;
  EXEC sys.sp_rename N'dbo.New', N'Original', 'OBJECT';
COMMIT TRANSACTION;
GO

INSERT dbo.Original(ID,name) VALUES(3,N'splunge');
UPDATE dbo.Original SET ID = 6 WHERE ID = 1;
GO

SELECT * FROM dbo.Original;
GO

Результати:

ID  name
--  -------
2   bar
3   splunge
6   foo

Тепер почистіть:

DROP TABLE dbo.Original;

Це лише операція з метаданими, без руху даних, і блокує лише інших користувачів під час оновлення метаданих. Але, правда, це дуже спрощений приклад. Якщо у вас є закордонні ключі або ви використовуєте інші функції, такі як реплікація, засіб збору даних, відстеження змін тощо, можливо, вам доведеться відключити або видалити деякі з них, перш ніж вносити ці зміни (я не перевіряв усі комбінації). Спеціально щодо іноземних ключів див. Цю пораду, яка показує, як генерувати сценарії для скидання та відновлення всіх (або вибраних) обмежень зовнішнього ключа.

Крім того, вам потрібно буде оновити код програми, щоб не очікувати, що SQL Server заповнить цей стовпець, і перевірити будь-які вставки або виписки, які можуть залежати від порядку стовпців або стовпців, які вони повинні вказати. Як правило, я б привітався з усією базою коду за будь-яку згадку про цю таблицю.

Також перегляньте цей сценарій від Іціка Бен-Гана (джерело: ця стародавня стаття ) для іншого способу вирішення цього питання, але тут є рух руху даних, тому він не доставляє вимоги "немає або мінімального простою".


3
Я хотів би заохотити всіх, хто заходить, щоб запросити два елементи з'єднання. Наскільки важко реалізувати функцію ALTER COLUMN, яка вмикає або вимикає булеву ідентичність ?! Болісно обійтися.
usr

Треба визнати, я чомусь подумав, що ..SWITCH..працює лише для таблиць, де визначено принаймні один розділ.
RBarryYoung

Просто хочу додати, що SWITCHне вимагає Enterprise Edition, хоча розбиття таблиць є.
Дан Гузман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.