Изменение столбца первичного ключа таблицы, на который ссылается внешний ключ в других таблицах - PullRequest
0 голосов
/ 30 мая 2011

В нашей БД (на SQL Server 2005) у нас есть таблица «Клиенты», первичным ключом которой является Клиентский код, суррогатный ключ bigint IDENTITY (1,1);на таблицу ссылается ряд других таблиц в нашей БД через внешний ключ.

Новая реализация CR, которую мы оцениваем, потребует от нас изменить тип столбца ID на varchar, алгоритм генерации клиентского кода будет смещен спростое числовое преобразование в строго 2-символьное представление с кодами в диапазоне от 01 до 99, а затем прогрессирование выглядит следующим образом:

1A -> 2A -> ... -> 9A -> 1B -> ... 9Z

Я довольно новичок в проектировании баз данных, но чувствую здесь некоторые серьезные проблемы.Прежде всего, как насчет этого алгоритма генерации клиентского кода?Что, если мне нужно, чтобы код клиента выходил за пределы кода 9Z?

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

Ответы [ 4 ]

2 голосов
/ 30 мая 2011

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

1 голос
/ 30 мая 2011

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

Выполнение изменения является многошаговой операцией. Вам необходимо создать новое поле в основной таблице и во всех связанных с ней таблицах.

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

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

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

Производительность не обязательно является проблемой в SQL Server 2005 и 2008. Недавно мы претерпели изменения, в которых мы перешли от идентификаторов везде к 7 или 8 символьным «дружественным» кодам записей. Мы ожидали увидеть какое-то снижение производительности, но на самом деле мы увидели улучшение улучшение .

Мы также обнаружили, что нам нужен способ быстрой генерации кода. Наши коды состоят из двух частей: альфа-префикс из 3 символов и суффикс из 4 или 5 цифр Как только у нас появилось большое количество кодов (15000-20000), мы обнаружили, что он замедляет анализ кода в префикс и суффикс и находит наименьший неиспользуемый код (это заняло несколько секунд). По этой причине мы также храним префикс и суффикс отдельно (в таблице первичных ключей), чтобы мы могли быстро найти следующий доступный младший код с конкретным префиксом. Кэшированный префикс и суффикс сделали поиск почти платным.

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

Мы не используем ORM, поэтому я не знаю, что конкретно нужно знать об этом. У нас также есть порядка 60 000 первичных ключей в нашем самом большом экземпляре, но у нас есть сотни связанных таблиц и таблицы с миллионами связанных значений для кодовой таблицы.

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

0 голосов
/ 30 мая 2011

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

0 голосов
/ 30 мая 2011

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

# test.rb -- generate a peculiar sequence of two-character codes.
i = 1
('A'..'Z').each do |c|
  (1..9).each do |n|
    printf("'%d%s', %d\n", n, c, i)
    i += 1
  end
end

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

Я бы больше беспокоился о диапазоне, чем об алгоритме.Если вы правы насчет требования, вы ограничены 234 кодами клиентов.Если вы ошибаетесь, и диапазон расширяется от «1A» до «ZZ», вы ограничены менее чем тысячей.

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

  • Создайте и заполните таблицу из двух столбцов, чтобы отобразить существующие обозначения в новый CHAR (2).
  • Создайте новые столбцы CHAR (2) во всех нужных им таблицах.
  • Обновите все новые столбцы CHAR (2).
  • Создайте новые ограничения NOT NULL UNIQUE или PRIMARY KEY и новые FOREIGN KEY ограничения на новые столбцы CHAR (2).
  • Переписать код пользовательского интерфейса (?) Для назначения новых столбцов.( Может не понадобиться, если вы переименуете новый столбец CHAR (2) и старый BIGINT.)
  • Установите целевую дату для удаления старых столбцов BIGINT и ограничений.
  • И т. Д.
...