В некоторые из моих таблиц я хочу добавить «second_primary_key», который будет uuid или какой-нибудь случайный длинный ключ. Мне это нужно, потому что для некоторых таблиц я не хочу предоставлять целые числа своему веб-приложению. То есть на странице "/ invoices" у меня есть список счетов и ссылка на "/ invoices /: id", где: id - это целое число. Я не хочу, чтобы пользователь знал, сколько там счетов в моей системе, поэтому вместо "/ invoices / 123" я хочу использовать его "second_primary_key", чтобы URL был "/ invoices / N_8Zk241vNa"
То же самое касается других таблиц, где я хочу скрыть реальный идентификатор.
Интересно, это обычная практика? Какой лучший способ реализовать это?
И как в конце концов называется эта техника, так что я делаю поиск по ней?
Ответы:
Вы можете добавить столбец UUID, но вам действительно не нужно (и не должно). Это проблема уровня представления. Вы не мечтали бы сказать, храня валютную ценность как 1 999 $ так же как 1999.
Вам просто нужен какой-то способ скрыть ценность приложения на лету. Вы можете сделать это в самом приложении или в виде базы данных.
Поскольку мы говорим только об одном значении, возможно, рассмотрим двухстороннее шифрование, такое как AES или подобное, - чем легче, тем лучше.
Хэширование может быть другой возможностью - это зависит от того, хотите ли вы вернуть номер счета-фактуры, поскольку хэширование - это один из способов.
источник
Наличие «альтернативного первичного ключа» является хорошо известным понятием в моделировании реляционных баз данных, его называют «альтернативным ключом», а иногда и «вторичным ключом». Набор «потенциальных первичных ключей» называется «ключами-кандидатами». См. Https://beginnersbook.com/2015/04/alternate-key-in-dbms/
Как вы реализуете это полностью зависит от вас, особенно если вы хотите скрыть общее количество записей. Не существует «наилучшего способа», вы должны проверить свои требования, такие как разрешенный или полезный набор символов, максимальную длину, если вы хотите, чтобы идентификаторы чувствительны к регистру или нет, если вы хотите, чтобы они были читаемыми в распечатанном счете, должен иметь возможность перепечатать их на телефоне без ошибок и тд.
источник
Большинство счетов-фактур имеют номер счета-фактуры, который по большинству правил бухгалтерского учета должен быть последовательным, или бухгалтер может не подписывать результаты по итогам года, или IRS (или аналогичный в вашей стране) может захотеть провести полный аудит ваших вкладок.
Пользователь может определить по номеру счета-фактуры, сколько клиентов вы обслуживали или сколько времени прошло до того, как вы изменили стратегию нумерации счетов.
Сколько счетов хранится в базе данных, не является показателем общей суммы ваших счетов. Есть и другие способы выяснить это, в том числе запросить ваши отчеты за год в Торговой палате.
Однако я бы заблокировал счет-фактуру за экраном входа пользователя в систему, поэтому не каждый может его запросить. Затем при входе пользователя в систему они могут использовать методологию ajax для запроса своих неоплаченных счетов и т. Д. Это защищает ваши данные, скрывает URL-адрес с помощью ajax (обычно никто не удосуживается взглянуть на детали того, как создается запрос ajax). и вы контролируете, как данные отображаются и предлагаются.
источник
Возможно, вы сможете использовать хеш-коды для этого, он предназначен именно для этого сценария.
Он закодирует идентификатор вашей базы данных в короткий хэш (аналог URL-адреса видео на YouTube) и не потребует добавления дополнительных ключей к вашей таблице.
источник
Вы можете создать другой уникальный ключ, но не должны. Не по указанной причине. Есть более простые способы скрыть размеры таблицы.
Хранение
N_8Zk241vNa
стоит 12 байт на строку в таблице и даже больше в индексе. Это довольно расточительно для того, что вам нужно.Шифрование целого числа
id
не требует места и практически ничего не значит во время выполнения. Как вы это сделаете, зависит от вашего языка программирования и / или вашей базы данных.Обратите внимание, что с AES вы получите 128-битное целое число, что означает 22 символа в base64, вероятно, больше, чем вы хотите. Шифр с размером блока 64, такой как DES или 3DES, дает вам 11 символов, как вы хотите.
Используйте разные ключи для разных таблиц.
Если все, что вам нужно, это скрыть размеры таблиц, вы можете использовать общую последовательность для всех таблиц. Обратите внимание, что это может быть узким местом, если во многих ваших таблицах есть частые вставки. С чем-то вроде Hibernate и алгоритма Hi-Lo эта проблема исчезает.
источник
byte[]
, вы можете записать своиid
четыре или восемь байтов, добавить уникальный номер таблицы и зашифровать (входные данные должны быть ровно 16 байтов). Если есть режимы на выбор, ЕЦБ прав.ИМХО создание двух разных первичных ключей невозможно. Конечно, вы можете поместить этот uuid в БД, чтобы он был «псевдонимом» для текущего первичного ключа. Вы можете поместить индекс над этим столбцом с уникальным ограничением, но первичный ключ (по своей сути) является единым в одной таблице. Может быть составной первичный ключ, но это не то, что вы ищете.
Поэтому я предлагаю поместить его туда, но только с указателем. Вы можете создать компонент обработки для запроса данных по PK, а также по другим уникальным столбцам. При обработке запроса "/ invoices / ..." просто проверьте параметр - если он целочисленный, ищите идентификатор, иначе ищите uuid. Или вы можете использовать поиск uuid как запасной вариант, когда поиск по идентификатору ничего не нашел.
И о генерации некоторых «случайных» uuids: почему бы не что-то вроде «взять ID, добавить CONSTANT, преобразовать в шестнадцатеричное». Уникальность идентификатора обеспечит уникальность uuid, шестнадцатеричное число труднее читать для обычных смертных + добавление константы позволит избежать использования uuid, например 00000001.
источник
/invoices/123
,/invoices/124
, ...) так что вы будете искать только по UUID из URL.Если оба ключа указывают на один и тот же факт, и они никогда не столкнутся. Почему бы не извлечь другой ключ из исходного, используя некую скалярную функцию, которая создаст пользовательский хэш-код вашего исходного ключа.
В качестве альтернативы вы можете создать таблицу сопоставления приложений, в которой будут храниться обе версии ключа. эта таблица будет действовать как словарь для поиска вторичного ключа.
Насколько я понимаю, ключи - это неявные индексы, и чем больше вы добавляете индексы, тем медленнее будут вставки.
источник
Другой подход для вашего конкретного случая использования состоит в том, что вместо изменения базы данных и приложения вы можете просто создать собственный маршрут к счетам, чтобы / invoices /: f (id), где f (id), была некоторой функцией идентификатора.
Пользовательский маршрут отвечает за сопоставление запроса с правильным действием на стороне сервера.
источник
Это вполне приемлемая практика, также называемая «Альтернативный ключ» (АК). По сути, AK - это еще один уникальный индекс или уникальное ограничение.
Вы даже можете создать ограничения внешнего ключа на основе вашего AK.
Возможный вариант использования подобен тому, что вы объяснили: у вас есть кластеризованный PK на постоянно увеличивающемся идентификационном номере, но вы не хотите, чтобы этот номер отображался или использовался в качестве критерия поиска, потому что его можно просто угадать. Кроме того, у вас есть случайный уникальный идентификатор или ссылочный номер в виде AK, и это тот идентификатор, который вы предоставляете пользователю.
источник
Есть несколько видов ключей / индексов. Первичный ключ - это специальный уникальный индекс, и, как показывают ответы, вы, безусловно, можете создать еще один уникальный ключ. И я согласен, что лучше не раскрывать внутренности вашей базы данных, если на то нет веской причины.
Поскольку этот вопрос относится к счетам и номерам, возможно, стоит изучить, как бухгалтерская отрасль ожидает, что номера счетов будут выглядеть: http://smallbusiness.chron.com/assign-invoice-numbers-52422.html
Может показаться беспорядочным наличие внутреннего идентификатора, который является первичным ключом, и другого уникального поля с видимым номером счета приложения / клиента. Но это не так нечисто, когда, скажем, год спустя, клиент хочет принять новую схему нумерации счетов. В этом случае вы бы не мешали внутреннему идентификатору и его отношениям в других таблицах перенумеровать весь шарик воска. Вы бы сохранили свой внутренний идентификатор как есть и изменили бы номер внешнего счета.
В идеале вы стараетесь не связывать таблицы вместе по ключам / внешним ключам, которые могут измениться, и сохраняете свои внутренние таблицы и отношения прозрачными для уровня приложения.
источник
Действуй.
Это не отличается от поля "slug", которое часто встречается в статьях блога и тому подобном - уникальный способ ссылки на запись базы данных отдельно от первичного ключа, пригодный для использования в URL. Я никогда не слышал, чтобы кто-то спорил против них.
источник