Исправление несоответствий БД — поля ID

Я унаследовал (Microsoft?) базу данных SQL, которая не была идеальной в своем первоначальном состоянии. В нем еще есть очень странные вещи, которые я пытаюсь исправить — одна из них — несогласованные записи ID.

В таблице счетов каждая запись имеет номер, называемый идентификатором счета, на который ссылаются в нескольких других таблицах (примечания, оборудование и т. д.). Проблема в том, что числа (по какой-то случайной причине) - варьируются от -100000 до +2000000, когда всего около 7000 записей.

Есть ли хороший способ перенумеровать их при изменении соответствующих номеров в других таблицах? В моем распоряжении также есть ColdFusion, так что все, что работает с SQL и/или то, что я приму.


person Davis    schedule 15.01.2009    source источник
comment
Почему это проблема? Какими должны быть идентификаторы?   -  person Tom H    schedule 15.01.2009


Ответы (6)


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

person Cade Roux    schedule 15.01.2009
comment
+1 Согласен, оставьте такие вещи в покое, если только система не полностью заблокирована или не приближается к краху. - person Kev; 15.01.2009
comment
Я не эксперт в базах данных, и я уже перенес данные в таблицы, которые я сделал, поэтому мне нечего делать. Исправление этих чисел не помешало бы разработке пользовательского графического интерфейса, которым я занимаюсь. - person Davis; 15.01.2009
comment
Но что вам даст исправление этих цифр? Когда у вас есть тысячи или миллионы суррогатных ключей, вы к ним не привязываетесь ;-) - person Cade Roux; 15.01.2009
comment
Да, я полагаю, я просто использую CF, чтобы исправить негативы, которые беспокоят мой OCPD, а затем попытаюсь убедить своего полутехнического босса, что это хороший способ. - person Davis; 15.01.2009
comment
iuvat, как сказал Кейд, не привязывайтесь к этим числам, вы можете рассматривать идентификаторы как указатели в C или ссылки на объекты в других языках программирования. Значение не имеет значения, важно то, что оно ссылается на правильный объект (правильная строка в таблице). - person kristof; 15.01.2009
comment
+1 Кристофу. Если эти значения ничего не значат в «деловом» смысле и их единственной целью является создание отношений между данными, я бы оставил их в покое навсегда. - person Kev; 15.01.2009

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

person robsymonds    schedule 15.01.2009
comment
Верно. Для IDentifiers обычно не быть смежными, и я не понимаю, почему это проблема. - person bortzmeyer; 16.01.2009

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

person HLGEM    schedule 15.01.2009
comment
Поверьте мне, я знаю эту БД от начала до конца, перенеся всю информацию из плохо спроектированной, в которой она была. Кроме того, я лично написал единственное приложение, которое взаимодействует с ней, поэтому я почти уверен положительные числа ничего не повредят. Это был просто плохой оригинальный программатор. - person Davis; 17.01.2009

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

Ознакомьтесь со сценарием здесь: http://vyaskn.tripod.com/sql_server_search_and_replace.htm

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

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

person SqlRyan    schedule 15.01.2009
comment
База устроена черт знает как - меня тогда там не было - и там разные странности. Когда-то число под названием servicecallID было датой, а не возрастающим числом. Он был пропущен до 2005xxxx, а затем снова начал увеличиваться на единицу. - person Davis; 15.01.2009

С ColdFusion это не должно быть геркулесовой задачей, но это будет грязно, и вам придется быть осторожным. Один из методов, который вы могли бы использовать, — создать сценарий для базы данных, а затем сгенерировать совершенно новую пустую схему таблицы. Установите идентификатор учетной записи в качестве поля идентификации в новой базе данных.

Затем, используя ColdFusion, напишите запрос, который извлечет все данные старой учетной записи и вставит их в новую базу данных одну за другой. Для каждой строки пусть новая база данных назначит новый идентификатор. После каждой вставки извлекайте новый идентификатор (используя либо @@IDENTITY, либо MAX(accountID)) и сохраняйте новый и старый идентификаторы вместе во временной таблице, чтобы вы знали, какие старые идентификаторы принадлежат каким новым идентификаторам.

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

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

person Justin Scott    schedule 15.01.2009
comment
Я сделал страницу coldfusion для одной из небольших таблиц, но для этой она занимает слишком много времени, и по какой-то причине я получаю несоответствия. у вас есть макет кода для хорошего пути? - person Davis; 15.01.2009
comment
Никогда не используйте @@identity для извлечения нового идентификатора, вы можете получить неправильные результаты и нарушить целостность данных. Вместо этого используйте scope_identity(). - person HLGEM; 15.01.2009

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

ALTER TABLE accounts
ADD new_accountID int IDENTITY

ALTER TABLE notes
ADD new_accountID int

ALTER TABLE equipment
ADD new_accountID int

Затем вы можете сопоставить столбец new_accountID в каждой из ваших ссылочных таблиц с таблицей учетных записей.

UPDATE notes
SET new_accountID = accounts.new_accountID
FROM accounts
INNER JOIN notes ON (notes.accountID = accounts.accountID)

UPDATE equipment
SET new_accountID = accounts.new_accountID
FROM accounts
INNER JOIN equipment ON (equipment.accountID = accounts.accountID)

На данный момент каждая таблица имеет как accountID со старыми ключами, так и new_accountID с новыми ключами. Отсюда должно быть довольно просто.

  1. Сломать все внешние ключи на accountID.
  2. В каждой таблице UPDATE [таблица] SET accountID = new_accountID.
  3. Повторно добавьте внешние ключи для accountID.
  4. Удалите new_accountID из всех таблиц, так как он больше не нужен.
person Patrick McElhaney    schedule 15.01.2009