Почему удаление свойства Identity для столбца не поддерживается

11

Я читал, что после SQL Server 2000 была удалена возможность «отождествления» столбца идентификаторов. И это было «По замыслу» (не просто отсутствующая функция).

Вот пример, который я нашел в блоге . Это включает обновление системных таблиц. (И эта возможность была удалена после SQL Server 2000.) Я понимаю, что делать это с помощью системных таблиц не очень хорошая идея. Мне просто интересно, почему нет возможности сделать это по-другому.

Работа над этим вызовет у меня значительный объем работы. (Копирование многих сотен миллионов строк в новые таблицы в среде, не допускающей простоев.)

Поэтому я подумал, что спросить «Почему».

Что изменилось в Sql Server 2005 и более поздних версиях, что сделало это плохим? Или это всегда было плохо и просто не заперто?

Какая «передовая практика» (или аналогичный принцип) будет нарушена, если сделать столбец идентификации нормальным столбцом снова?

-

Обновление, чтобы ответить на запрос «почему я это делаю»:
Это очень общий итог: я собираюсь начать добавлять разделы в свои таблицы. (Так что я могу архивировать / удалять старые данные.) Это все легко. Но иногда мне нужно переместить запись в другой раздел, чтобы она не удалялась (когда раздел подходит для архивирования / удаления). (У меня столбец разделения увеличивается на 2, так что всегда есть место для перемещения строки в другой раздел.)

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

Поэтому я хочу использовать последовательность вместо столбца идентификаторов. Но этот переключатель очень и очень сложен для больших баз данных.

Vaccano
источник

Ответы:

22

Ваш вопрос, по сути:

Почему я больше не могу делать эту рискованную вещь, которую мне никогда не следовало делать?

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

Тем не менее, как насчет того, чтобы ответить на этот вопрос?

Как удалить свойство IDENTITY столбца с минимальным временем простоя или без него?

Вы можете легко это сделать, используя ALTER TABLE ... SWITCHтехнику, которую, я уверен, я впервые узнал от нашего собственного Пола Уайта в обходных решениях для Connect # 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, хотя разбиение таблицы делает.
Дан Гузман