Уникальные, но простые идентификаторы в базе данных в SQL Server - PullRequest
47 голосов
/ 06 апреля 2009

Во-первых, я знаю этот вопрос , и предложение (с использованием GUID) не применимо в моей ситуации.

Мне нужны простые UID, чтобы мои пользователи могли легко передавать эту информацию по телефону:

Здравствуйте, у меня проблема с заказом 1584

в отличие от

привет, у меня проблема с заказом 4daz33-d4gerz384867-8234878-14

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

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

Моя текущая идея состоит в том, чтобы использовать столбцы идентификаторов с различными начальными значениями 1, 2, 3 и т. Д. И значением приращения 100.

Это поднимает несколько вопросов:

  • Что если я в итоге получу более 100 типов объектов? Конечно, я могу использовать 1000 или 10000, но что-то, что плохо масштабируется, "пахнет"

  • Существует ли вероятность того, что начальное число "потеряно" (во время репликации, проблемы с базой данных и т. Д.)

  • в целом, есть ли другие проблемы, о которых мне следует знать?

  • возможно ли использовать нецелое число (в настоящее время я использую bigints) в качестве столбцов идентификаторов, чтобы я мог добавить к идентификатору идентификатор, представляющий тип объекта? (например, столбец varchar)

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

  • Существуют ли другие умные способы решения моей проблемы?

Ответы [ 11 ]

56 голосов
/ 06 апреля 2009

Почему бы не использовать идентификаторы во всех таблицах, но каждый раз, когда вы представляете их пользователю, просто добавьте один символ для типа? например O1234 - это заказ, D123213 - это доставка и т. Д.? Таким образом, вам не нужно придумывать какую-то безумную схему ...

13 голосов
/ 06 апреля 2009

Обрабатывайте это в пользовательском интерфейсе - добавляйте префиксную букву (или буквы) на идентификационный номер при сообщении об этом пользователям. Таким образом, o472 будет заказом, b531 будет счетом и так далее. Людям довольно удобно смешивать буквы и цифры, когда они дают «цифры» по телефону, и они более точные, чем с прямыми цифрами.

12 голосов
/ 06 апреля 2009

Вы можете использовать автоинкрементный столбец для генерации уникального идентификатора. Затем есть вычисляемый столбец, который принимает значение этого столбца и добавляет к нему фиксированный идентификатор, который отражает тип объекта, например OR1542 и DL1542, будет представлять заказ № 1542 и доставку № 1542 соответственно. Ваш префикс может быть увеличен настолько, насколько вы хотите, и формат может быть организован так, чтобы помочь различать элементы с одинаковым значением автоинкремента, скажем, OR011542 и DL021542, с префиксами OR01 и DL02.

3 голосов
/ 02 мая 2009

Почему не простое представление Bigint в Base36? http://en.wikipedia.org/wiki/Base_36

3 голосов
/ 16 апреля 2009

Проект намеренного программирования MS имел систему GUID-to-word, которая давала произносимые имена из случайных идентификаторов

.
3 голосов
/ 06 апреля 2009

Я бы реализовал, определив общую корневую таблицу. Из-за отсутствия лучшего названия назовите его Entity. Таблица Entity должна иметь как минимум один столбец Identity. Вы также можете включить другие поля, которые являются общими для всех ваших объектов, или даже метаданные, которые говорят вам, что эта строка является порядком, например.

Каждая из ваших фактических таблиц Order, Delivery ... будет иметь ссылку FK на таблицу Entity. Это даст вам один уникальный идентификатор столбца

Использование семян, по моему мнению, плохая идея, и она может привести к проблемам.

Редактировать

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

После того, как я написал этот ответ, я немного подумал о том, почему вы это делаете, и пришел к тому же выводу, что и Мэтт.

1 голос
/ 17 апреля 2009

Я использую алгоритм высокого / низкого для этого. Я не могу найти описание для этого онлайн, хотя. Об этом должен быть блог.

В моей базе данных есть таблица идентификаторов с полем счетчика. Это самая высокая часть. В моем приложении у меня счетчик от 0 до 99. Это самая низкая часть. Сгенерированный ключ: 100 * high + low.

Чтобы получить ключ, я делаю следующее

initially high = -1
initially low = 0

method GetNewKey()
begin
  if high = -1 then
    high = GetNewHighFromDatabase

  newkey = 100 * high + low.
  Inc low
  If low = 100 then
    low = 0
    high = -1

  return newKey
end

Реальный код более сложен с блокировками и т. Д., Но это общая суть.

Существует несколько способов получения высокого значения из базы данных, включая ключи auto inc, генераторы и т. Д. Лучший способ зависит от используемой вами базы данных.

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

1 голос
/ 16 апреля 2009

Мы столкнулись с похожей проблемой в проекте. Мы решили это, сначала создав простую таблицу, в которой есть только одна строка: BIGINT, установленный в качестве идентификатора автоинкремента. И мы создали sproc, который вставляет новую строку в эту таблицу, используя значения по умолчанию и внутри транзакции. Затем он сохраняет SCOPE_IDENTITY в переменной, откатывает транзакцию и затем возвращает сохраненную SCOPE_IDENTITY.

Это дает нам уникальный идентификатор в базе данных без заполнения таблицы.

Если вы хотите знать, к какому объекту относится идентификатор, я потеряю откат транзакции, а также сохраню тип объекта рядом с идентификатором. Таким образом, выяснить, к какому объекту относится идентификатор, остается только один выбор (или внутреннее соединение).

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

У меня была похожая ситуация с проектом.

Мое решение: по умолчанию пользователи видят только первые 7 символов GUID.

Достаточно случайно, что столкновения крайне маловероятны (1 на 268 миллионов), и это эффективно для разговора и набора текста.

Внутренне, конечно, я использую весь GUID.

0 голосов
/ 16 апреля 2009

Может быть вариант itemType-year-week-orderNumberThisWeek?

o2009-22-93402

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

...