Создание уникального идентификатора (PIN) для каждой записи таблицы - PullRequest
4 голосов
/ 26 июля 2010

Я хочу создать уникальный PIN-код в таблице, но не инкрементный, чтобы людям было сложнее угадывать.В идеале я хотел бы иметь возможность создать это в SQL Server, но я могу сделать это через ASP.Net при необходимости.

РЕДАКТИРОВАТЬ

Извините, если я не был 'Понятно: я не ищу GUID, так как все, что мне нужно, это уникальный идентификатор для этой таблицы;Я просто не хочу, чтобы это было постепенно.

Ответы [ 6 ]

4 голосов
/ 26 июля 2010

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

CREATE TABLE MyTable (
   ...
   PIN uniqueidentifier NOT NULL DEFAULT newid()
   ...
)

Уникальный идентификатор гарантированно будет уникальным не только для этой таблицы, но и для всех таблиц.

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

   SELECT RIGHT(REPLACE((SELECT PIN from MyTable WHERE UserID=...), '-', ''), 4/*PinLength*/)

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

РЕДАКТИРОВАТЬ: Если вам нужен маленький ПИН-код с гарантированной уникальностью, сложная часть заключается в том, что вам необходимо знать как минимум максимальное количество пользователей, чтобы выбрать подходящий размер пина. По мере увеличения количества пользователей увеличивается вероятность конфликта ПИН-кодов. Это похоже на проблему Coupon Collector и приближается к n log n сложности, что приведет к очень медленным вставкам (время вставки пропорционально количеству существующих элементов, поэтому вставка M элементов становится O (N ^ 2) )). Самый простой способ избежать этого - использовать большой уникальный идентификатор и выбрать только его часть для своего PIN-кода, при условии, что вы можете отказаться от уникальности значений PIN-кода.

РЕДАКТИРОВАТЬ2:

Если у вас есть такое определение таблицы

CREATE TABLE YourTable (
    [id] [int] IDENTITY(1,1) NOT NULL,
    [pin]  AS (CONVERT(varchar(9),id,0)+RIGHT(pinseed,3)) PERSISTED,
    [pinseed] [uniqueidentifier] NOT NULL
)

Это создаст pin из pinseed уникального идентификатора и идентификатора строки. (RAND не работает - поскольку SQL-сервер будет использовать одно и то же значение для инициализации нескольких строк, это не относится к NEWID ())

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

1 голос
/ 26 июля 2010

То, что вы хотите, это GUID

http://en.wikipedia.org/wiki/Globally_unique_identifier

Большинство языков имеют своего рода API для генерации этого ... поиск в Google поможет;)

0 голосов
/ 26 июля 2010

Используйте случайное число.

SET @uid = ROUND (RAND () * 100000)

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

После того, как число сгенерировано, у вас есть несколько вариантов.1) ВСТАВЬТЕ значение в цикл повторения.Если вы получили ошибку дублирования, восстановите значение (или попробуйте значение +/- 1) и повторите попытку.2) Сгенерируйте значение и найдите существующие уникальные идентификаторы MAX и MIN.

DECLARE
    @uid    INTEGER
SET @uid = ROUND(RAND() * 10000, 1)
SELECT @uid
SELECT MAX(uid) FROM table1 WHERE uid < @uid
SELECT MIN(uid) FROM table1 WHERE uid > @uid

Значения MIN и MAX дают вам диапазон доступных значений для работы, если случайное значение уже назначено.

0 голосов
/ 26 июля 2010

Вы можете использовать следующее для создания BIGINT или другого типа данных.

SELECT CAST(ABS(CHECKSUM(NEWID()))%2000000000+1 as BIGINT) as [PIN]

Это создает число от 1 до 2 миллиардов.Вы будете имитировать некоторый уровень случайности, поскольку он получен из функции NEWID.Вы также можете отформатировать результат по своему желанию.

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

0 голосов
/ 26 июля 2010

Имейте в виду, что, запрашивая уникальный ПИН-код (что редко), вы ограничите максимальное количество разрешенных пользователей спецификацией ПИН-кода.Вы уверены, что хотите это?

Не очень элегантное решение, которое работает, если использовать поле UNIQUE, а затем цикл, пытаясь вставить случайно сгенерированный PIN-код до тех пор, пока вставка не будет успешной.

0 голосов
/ 26 июля 2010

Как насчет столбца типа UNIQUEIDENTIFIER со значением по умолчанию NEWID ()?

Это создаст новый GUID для каждой строки.

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