Столбец «Сбросить личность» в SQL Server - PullRequest
6 голосов
/ 19 марта 2009

Я делаю базу данных SQL, в которой хранятся контакты. Я хочу иметь возможность удалять контакты, и правильный идентификатор для каждого контакта имеет решающее значение для моего программного обеспечения, подключающегося к нему. Допустим, у меня есть контакт с Джеймсом, и он первый. Его идентификатор равен 0. Я добавляю Мэри, а ее идентификатор равен 1. Если я удаляю Джеймса, как идентификатор Мэри можно установить равным 0 вместо того, чтобы оставаться 1? Это нужно сбросить, так как она первая сейчас. Другими словами, как я могу сбросить все идентификаторы в базе данных, когда кто-то удаляется? Спасибо

Ответы [ 10 ]

16 голосов
/ 19 марта 2009

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

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

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

6 голосов
/ 19 марта 2009

Это будет очень медленно, когда у вас будет больше, чем тривиальное количество записей в базе данных. Столбец идентификации не будет работать для вас, вам нужно выполнить некоторые пользовательские tsql, чтобы продолжать изменять все числа - но очень плохая идея, imo.

Почему бы не использовать отметку даты / времени, если вам нужно отслеживать, в каком порядке они были добавлены.

Вам нужно переосмыслить свой дизайн.

5 голосов
/ 19 марта 2009

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

Вместо этого, почему бы не добавить столбец "External_ID", которым вы управляете? Или нумеровать их в запросе динамически (с вычисляемым столбцом?)

4 голосов
/ 19 марта 2009

Идентификатором является уникальный идентификатор строки.

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

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

3 голосов
/ 20 марта 2009

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

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

UPDATE table
SET secondaryID = secondaryID - 1
WHERE secondaryID > (SELECT secondaryID FROM table WHERE primaryID = [id to delete]);

DELETE FROM table
WHERE primaryID = [id to delete];

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

3 голосов
/ 19 марта 2009

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

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

2 голосов
/ 19 марта 2009

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

1 голос
/ 02 июня 2009

1-минутный поиск в Google дал мне страницу, которую я не могу отобразить. Google это и это будет ваша первая ссылка на 01.06.2009: tsql исправить "столбец идентичности"

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

Если ваша таблица контактов является вашей ТОЛЬКО таблицей или имеет отношения НОЛЬ, основанные на этом поле идентификатора, вы можете установить для свойства Identity значение NO, изменить нумерацию значений с 1 на COUNT (ID), затем установить для свойства Identity значение YES, и повторно заполнить личность для завершения, используя:

ОБЪЯВИТЬ @MaxID INT

SELECT @MaxID = COUNT (ID) ИЗ TableID

DBCC CHECKIDENT ('TableID', RESEED, @MaxID)

В этом сценарии вы можете использовать приведенный выше сценарий повторного заполнения после каждого набора удалений (но измените COUNT (ID) на MAX (ID), как только все будет правильно и правильно настроено, это добавляет небольшую скорость по мере увеличения таблицы ), до каких-либо дополнительных вставок или обновлений ограничений внешнего ключа. Убедитесь, что вы используете TRANSACTIONS, обернутые вокруг блоков удаления и повторного заполнения, и убедитесь, что в таблице разрешены только синхронные транзакции, это предотвратит потерю данных в середине повторного заполнения.

Комплекс а? Вот почему лучше начать с правой ноги. ;) (Я узнал об этом из своего опыта) Если у вас есть вопросы, напишите мне на mraarone et yahoo d0t com.

0 голосов
/ 27 июня 2009

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

DBCC CHECKIDENT ({имя таблицы}, повторное заполнение, 0)

* Сначала удалить все строки из всех таблиц, используя идентификатор

0 голосов
/ 22 мая 2009

Я написал приложение для управления многоуровневой программой продаж. Конечно, люди бросают. У нас тоже нужно было вставлять людей.

Вы на правильном пути с одной модификацией.

Идентификационный номер (ID) и порядковый номер (seq) - это две разные вещи. Они вообще не имеют никакого отношения друг к другу.

Никогда не меняйте ID. После назначения всегда назначается.

Создайте столбец (cNEXT) в своей таблице для последовательности и заполните ее идентификаторами. «Какой идентификатор должен быть следующим в этой последовательности?»

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

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

Надеюсь, это поможет! :)

...