TSQL: генерировать удобочитаемые идентификаторы - PullRequest
1 голос
/ 26 февраля 2009

У нас есть большая база данных с запросами, на каждую ссылку ссылается с помощью Guid. Guid не очень удобен для клиентов, поэтому мы хотим использовать дополнительный 5-значный «человеческий идентификатор» (хорошо, поскольку у нас, вероятно, не будет более 99999 активных запросов в любое время, и это нормально, если Humanuid ссылается на несколько запросов поскольку они не используются ни для чего важного).

1) Можно ли как-нибудь сбросить столбец IDENTITY на 1 после 99999?

Мой текущий способ решения этой проблемы - использовать столбец INT IDENTITY(1,1) NOT NULL, а при представлении HumanId взять HumanId % 100000.

2) Есть ли способ автоматически «случайным образом распределить» идентификаторы по [0..99999], чтобы два созданных друг за другом запроса не получали соседние идентификаторы? Я думаю, я ищу двустороннюю хэш-функцию "один к одному" ??

... В идеале я хотел бы создать это с помощью T-SQL, автоматически создавая эти идентификаторы при создании запроса.

Ответы [ 5 ]

3 голосов
/ 26 февраля 2009

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

РЕДАКТИРОВАТЬ: На заметку, это звучит как проблема «слой представления», который не должен быть в вашей базе данных. Ваш уровень представления вашего приложения должен иметь код, чтобы беспокоиться о представлении записи в удобочитаемой форме. Просто мысль ...

2 голосов
/ 26 февраля 2009

Если вам абсолютно необходимо сделать это в базе данных, то почему бы не получить дружественное человеку значение непосредственно из столбца GUID?

-- human_id doesn't have to be calculated when you retrieve the data
-- you could create a computed column on the table itself if you prefer
SELECT (CAST(your_guid_column AS BINARY(3)) % 100000) AS human_id
FROM your_table

Это даст вам случайное значение между 0 и 99999, полученное из первых 3 байтов GUID. Если вы хотите увеличить или уменьшить диапазон, отрегулируйте делитель соответствующим образом.

2 голосов
/ 26 февраля 2009

Я настоятельно рекомендую пересмотреть вашу логику. Ваш подход имеет несколько опасностей, в том числе:

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

  2. При назначении вручную сгенерированного / случайного идентификатора вам необходимо убедиться, что нескольким записям не присвоен один и тот же идентификатор. Существует несколько вариантов, которым вы должны следовать (например, при использовании транзакций), однако вы должны убедиться, что объем транзакций не оставит вас открытыми для проблем с блокировкой одновременных транзакций - это может вызвать несколько проблем. например. Спектакль. Лучше всего вам будет генерировать свой идентификатор извне (поскольку SQL не очень хорошо работает случайным образом), а затем применять уникальное ограничение для вашей БД, возможно, способом, предложенным Фирозом Ансари.

Если вы все еще хотите сбросить столбец идентификаторов, это можно сделать с помощью команды DBCC CHECKIDENT.

Пример генерации случайных начальных значений в SQL-сервере можно найти здесь: http://weblogs.sqlteam.com/jeffs/archive/2004/11/22/2927.aspx

1 голос
/ 26 февраля 2009

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

BatchId, HumanId

1, 1

1, 2

1, 3

.

.

1, 99998

1, 99999

2, 1

2, 2

3, 3

используйте MAX или ORDER BY DESC для получения следующего доступного HumanId с условием BachId

SELECT TOP 1 @NextHumanId=HumanId
FROM [THAT_TABLE]
ORDER BY BatchId DESC, HumanID DESC

IF @NextHumanId>=99999 THEN SET @NextHumanId=1

Надеюсь, это поможет.

0 голосов
/ 26 февраля 2009

У вас может быть таблица доступных HUMANID, каждый раз, когда вы добавляете запрос, вы можете произвольно извлекать HUMANID из таблицы (и УДАЛЯТЬ его), и каждый раз, когда вы удаляете запрос, вы можете добавить его обратно (путем ВСТАВКИ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...