Comments 186
Паспорт серии 0306 и паспорт серии 306 – это юридически разные документы.
Разве количество цифр в серии не всегда равно 4? Потому что я не очень понимаю, какая проблема в том, чтобы хранить 0306 как 306, если серия 306 невозможна. Никто не мешает отображать 306 как 0306, при этом.
Тоже не понимаю.
Если у нас реальная длина фиксированная, то пусть даже будет 0001 мы то все равно понимаем, что если длина числа равна 1, то нужно добавить лидирующие нули.
Всё так, можно и проверить, и добавить. Но в процессе работы с данными вы получаете дополнительный оверхед - нужно преобразовать в строку, проверить длину, при необходимости добавить ведущий ноль... Что самое забавное - вы будете делать это каждый раз, когда оно понадобится. Я не верю, что кому-то в голову придёт вычитать один раз и закэшить в памяти, чтобы потом всё время использовать это один раз полученное нормализованное значение.
А со строковым типом данных этого оверхеда нет.
Спорно, потому что вам нужно очищать тоггда данные от пробелов и спецсимволов. И также везде при вводе.
Далее, в большинстве систем, особенно в банковских, паспорт может быть иностранным.
Если вы говорите про семантику, то у паспорта НОМЕР, а не символьный или числовой идентификатор.
Номер это numeric. То, что в отображении используется форма с заполнением нулями слева не играет роли. Это отображение. Иногда это передача во внешние системы.
Не только лишь семантика рулит выбором, а вся совокупность сценариев использования. К примеру, телефонный номер это число, но есть код страны, а коды страны пересекаются. Есть +37, есть +373. Для логинов проще хранить единый номер. Но отобразить в форме код и номер ты не сможешь, выбрать по странам не сможешь.
Нормальный сеньор на ваш вопрос бы задал другой «а что за система и что вы собираетесь делать с этими номерами? Какие ограничения? Это только российские паспорта?»
Сеньор решает задачу системы, а не задачу хранения отдельно. В постгресе есть вычислимые на лету поля. Если номера паспортов и серий в числовом виде не пересекаются и в будущем не предполагается вводить иностранные паспорта и население рф не собирается выпрыгивать за диапазон в ближайшие сто лет, тогда, например, числовой тип на весь номер и две вычислимые колонки серии и номера с lpad абсолютно не являются криминалом.
Спорно, потому что вам нужно очищать тогда данные от пробелов и спецсимволов. И также везде при вводе.
Ну да... а при вводе в числовой тип всё это чистить не надо, да?
Если вы говорите про семантику, то у паспорта НОМЕР, а не символьный или числовой идентификатор.
У паспорта - идентификатор. Но какой-то товарищ назвал его "номер". И началося...
Так что дело да, в терминологии. В слове, применённом там, где его значение лишь частично соответствует смыслу. И бездумном ориентировании на слово, а не на суть.
Если номера паспортов и серий в числовом виде не пересекаются и в будущем не предполагается вводить иностранные паспорта ...
Ага... ещё добавьте "мамой клянусь".
Гарантии есть? нет. И сеньор ОБЯЗАН это и учесть, и предусмотреть.
Далее, в большинстве систем, особенно в банковских, паспорт может быть иностранным.
Именно. Вы можете гарантировать, что в этих случаях серия и/или "номер" не будут содержать буквы?
И "номером" это называется не везде. Чаще - именно "ID"
Только логика в вашей статье совершенно от другого.
На вопрос «в каком виде хранить номер паспорта» ответ не text, а встречный вопрос «какие ограничения, требования, сценарии использования, регуляторка». Номер паспорта является персданными и должен шифроваться.
Ваш ответ, данный в статье, не ответ сеньора.
нужно преобразовать в строку, проверить длину
а проверка "< 1000" для серии чем-то вас обидела? или "< 1000000000" для серии и номера сразу?
для ситуаций значений строго фиксированной длины рассуждения выглядят как бла-бла-бла, с одной стороны рассказ про 146 миллионов (и это надо еще помножить на несколько паспортов на каждого), а с другой экономия в несколько байт на строку - копейки
А со строковым типом данных этого оверхеда нет.
Весьма спорное утверждение.
Вы уверовали в то, что номер паспорта-это идентификатор. И забыли ответить на свои же вопросы.
Какова семантика этих данных? (Что они означают?)
Какие операции над ними будут производиться?
Серия паспорта-это весьма информативная составляющая. Первые 2 цифры-это код ОКАТО региона, где паспорт выдан. Вторые-год выпуска бланка. А вот номер паспорта-это как раз уникальный идентификатор.
Исходя из ответа на первый вопрос, я легко могу представить систему, в которой необходимо найти паспорта в определённом регионе, выданные в промежутке между скажем 2009 и 2010 годами.
И в этом случае числовой формат хранения даст более быстрый поиск.
Другое дело, что такого рода системы встречаются реже, чем те, где номер паспорта-просто идентификатор. Но вы же не конкретизировали, какие именно функции предоставляет система, а просто безапелляционно утверждаете, что мы имеем дело с обычным идентификатором.
я легко могу представить систему, в которой необходимо найти паспорта в определённом регионе, выданные в промежутке между скажем 2009 и 2010 годами.
..а потом окажется, что в некотором регионе у них остались невыданные бланки паспортов с прошлого года, и они решили «а чего добру пропадать» и выдали их не в том году.
«Всё не так плохо, как вам кажется. Всё гораздо, ГОРАЗДО хуже!» ©
Более того-так происходит почти всегда. Это нормально, когда прошлогодние бланки выдают в следующем году.
Но замените слово "выданные" на "напечатанные" и вот уже запрос имеет практический смысл.
По хорошему идентификатор не должен содержать смысловую нагрузку. А номер паспорта её содержит. А раз так, то можно и задачи на эту нагрузку придумать.
Всех желающих хранить номер серию и номер паспорта одной строкой не думая, как вы их будете использовать, предлагаю найти алгоритм поиска в такой строке паспортов, напечатанных в определённые, задаваемые пользователем, годы. Ну и естественно подумать над вопросом, а нет-ли в таком алгоритме оверхеда при работе со строками.
Все, кто предлагает НЕ хранить номер серию и номер паспорта одной строкой, не думают, что они будут со всем этим барахлом делать, когда бешеный принтер решит в очередной раз изменить формат.
Просто иногда люди, предлагающие не хранить одной строкой, сначала выясняют все обстоятельства работы системы, взвешивают за и против, а затем уже предлагают. А не просто предлагают сферического коня в вакууме.
С чего вы решили, что в системе номер паспорта будет служить именно идентификатором человека, а не источником данных по отпечатанным бланкам, например?
А потом выяснится, что при поиске сделать +1 все равно меньше нагрузка, чем искать по всему полю идентификаторов. Тем более код региона то точно не меняется
Первые 2 цифры-это код ОКАТО региона, где паспорт выдан. Вторые-год выпуска бланка.
Таки опять идентификатор. Формат которого вполне себе может быть изменён.
Формат ОКАТО -это 8-11 цифр. Согласен, что теоретически он может быть изменён. Но сравнивать-то придётся 2 цифры с 8ю. И как следствие придётся хранить сокращённый вариант.
Ещё раз-если идентификатор составной и несёт смысловую нагрузку, то всегда можно придумать задачи по этим смысловым полям.
Я ответил на ваш вопрос: какова семантика данных. А вот какие операции над ними будут проводиться-надо разбирать по конкретной системе и требованиям к ней.
Вы же продолжаете жить в парадигме, что "это просто идентификатор" Ничего кроме поиска по нему целиком не предполагая.
Вы же продолжаете жить в парадигме, что "это просто идентификатор" Ничего кроме поиска по нему целиком не предполагая.
Совершенно верно. Ибо здоровая паранойя - это профдеформация. Когда в сущность закладывается дополнительная информация, это, по моему совсем не скромному мнению, категорически неправильно. И использовать подобную информацию - совсем не стоит. Потому что вероятность пересмотра правил формирования весьма далека от нулевой.
И, кстати, именно в российском паспорте есть ещё целых два поля, которые более точно укажут, где и кем выдавался паспорт:
собственно, поле так и называет - "Паспорт выдан";
и ещё одно - "Код подразделения".
PS. Чем отличается проектировщик с опытом от начинающего, стартовый вопрос о типе хранения серии и номера паспорта, показывает вполне себе наглядно. Потому что, опытный проектировщик сразу вспомнит про паспорта иных государств, например.
Ну а чтобы жизнь мёдом не казалась, да и в порядке ненаучно-фантастического бреда, поднакину-ка я мал-мала на вентилятор. Как вам ситуация, когда наши безмерно уважаемые и горячо любимые законотворцы родят указивку о том, чтобы использовать 16-ричную систему счисления для серии и номера паспорта?
PSS. Глупость человеческая, в отличие от Вселенной, границ не имеет. :(
PSSS. Я подхожу к проектированию, следуя правилу: Проектируй систему из условия, что её будет эксплуатировать (пользоваться ей) достаточно квалифицированный моральный урод, который будет стремиться её (систему) сломать, а потом отыграться на проектировщике, до которого сможет добраться.
Так вопрос-то изначально не про дополнительные поля паспорта. С чего вы решили, что ваша система будет их содержать? Или что она будет с загран паспортами вообще работать? Возможно ваша система-это учёт бланков на госзнаке, где паспорт-вообще один из многих документов.
Я говорю о том, что проектировать хранение данных без учёта их применения вообще не правильно. И да, глупость границ не имеет. В том числе и при проектировании. И да, при проектировании надо всегда закладывать возможность изменения/расширения функциональности.
Мой изначальный пост был о том, что хранение номера паспорта в числовых полях не всегда даст оверхед по сравнению с хранением в строке.
И в этом случае числовой формат хранения даст более быстрый поиск.
С точки зрения SQL это тупое WHERE column BETWEEN. И я лично не верю в это ваше "более быстрый поиск". При наличии подходящего индекса скорость поиска должна быть достаточно близкой..
Серия паспорта-это весьма информативная составляющая. Первые 2 цифры-это код ОКАТО региона, где паспорт выдан. Вторые-год выпуска бланка.
А с этим утверждением возможны два варианта.
Первый - вы ГАРАНТИРУЕТЕ, что если при вводе мы разделим значение серии на два числовых поля, сохраним в БД только код ОКАТО и год выпуска, но не введённую серию, и в дальнейшем при запросе будем реконструировать значение серии, то у нас НИКОГДА не возникнет проблем - парсинга/преобразования, несоответствия введённого реконструированному и т.п.
Готовы гарантировать, что так и будет - сейчас, завтра, через десять лет? По-серьёзному, без всяких "ну а чё мне будет?". Если нет, то имеем второй вариант - нулевую ценность и практическую неприменимость сделанного утверждения.
А вы готовы гарантировать, что ваш where between обеспечит сопоставимую скорость по сравнению с поиском по числам при вводе пользователем 5-8 значений года для поиска? Нигде не напрягает, что мы там подстроки выделять будем?
Ещё раз, в статье правильно сказал автор, что надо думать не только о семантике, но и о возможных условиях использования. Естественно при проектировании надо закладывать возможные сценарии изменения функций.
Мой изначальный пост был про то, что использование использование числовых полей не всегда даёт оверхед при работе. Всё зависит от функций системы, которые вы старательно выводите из обсуждения, заменяя на наиболее частые варианты использования.
Ну и я не гарантирую, а говорю, что разделение серии на ОКАТО и год выпуска при вводе и хранении-это один из возможных вариантов использования. И в этом случае есть смысл думать о числовых полях. Разделять или нет-зависит от функций конкретной системы. Если у вас серия и номер паспорта-это просто идентификатор, то нафиг вам числовые поля не сдались. А вот если вы хотите на их основе какой-то анализ строить (без доп полей), то как хранить-зависит от того, что вы анализировать будете.
Первые 2 цифры-это код ОКАТО региона, где паспорт выдан.
Два моих и один паспорт супруги прямо таки всухую опровергают этот тезис: ни разу код региона выдачи не совпал с первыми двумя цифрами серии.
А вы не сталкивались с изменениями законодательства?
Завтра разрешат паспорта с 5 знаками и как вы поймёте, 1 - это 0001 или 00001?
Самое шикарное объяснение, почему нельзя хранить число и только на фронте рисовать ведущие нули.
Всегда интересно почему фронт должен что-то дорисовывать. В идеале он просто отрисовывает
честно говоря я его не понял, почему вы думаете что при этом изменении паспорт 0001 и 00001 это будут разные паспорта?
в системах с фиксированным числом разрядов при увеличении числа разрядов всегда делается пересчет - т.е. тот что был 0001 теперь 00001, у вас же система от добавления разряда не становится имеющей различное число знаков
В уважаемой фирме изменили заводские номера. Прибавили впереди два 0. Знаков стало больше, никто старые номера изменять не предлагал. 0012345678 и 12345678 - разные номера. В жизни так.
Возможно в уважаемых фирмах так можно (мне всеже сомнительно, т.к. судя по явно проставляемым ведущим нулям формат предполагает фиксированное число знаков, а эти номера фигурируют как минимум в учетных документах, и при таком подходе все документы содержащие 12345678 после изменения числа знаков оказались неверно заполненными), но как минимум с основным документом удоставеряющим личность это не так - формат его номера закреплен законом также как и, например, данные присутствующие на первой странице. Новый формат номера возможен для нового документа - например "паспорт гражданина РФ 2.0", но если появляется именно новый документ кажется что хранить его номер вместе с номерами другого документа идея сомнительная.
А если вставят буквы а не цифры
У моего знакомого была банковская карта. Пин - 5 цифр. На заправке автомат получает 4 цифры и бежит проверять. Не подходит. Несколько раз. Результат - блокировка карты. За границей, без денег...
В Китае ситуация обратная: пин должен быть не менее 5 символов, и соотечественники, не зная данной особенности и имея 4-х значный пин, блокировали себе карты, т.к. банкоматы тупо считают невалидным пин с количеством знаков менее 5.
А вот для правильного ввода 0 нужно вводить последним, а не первым символом.
Это излишне
Вы предлагаете классический антипаттерн – размазать ответственность за целостность данных тонким слоем по фронтенду или бизнес-логике. База данных должна хранить сам факт (идентификатор), а не математическую абстракцию, которую нужно каждый раз "собирать" костылями.
Представьте: завтра к этой базе подключается новый микросервис, BI-система для аналитики или понадобится сырая выгрузка в CSV. Каждому новому клиенту придется заново писать этот костыль с подстановкой нулей. А если кто-то забудет это сделать? Данные разъедутся. База должна гарантировать консистентность: положили строку – достали строку.
Представьте: завтра к этой базе подключается новый микросервис, BI-система для аналитики или понадобится сырая выгрузка в CSV. Каждому новому клиенту придется заново писать этот костыль с подстановкой нулей.
Нет, не придётся, в базах существуют представления.
Но, вообще говоря, мой комментарий был про то, что такой механизм хранения никак не ломает идентификацию человека.
Да и следуя вашей же аргументации, я могу вам сказать - представьте, что завтра в вашей базе начинают хранить не только российские, но и паспорта других стран. Или представьте, что завтра в вашей базе начинают хранить не только внутренние, но и загранпаспорта. Ваша предлагаемая схема готова к этому?
Представления отличный инструмент. Но зачем изначально создавать себе проблему на уровне хранения (терять данные), чтобы потом героически её решать через View? База должна хранить консистентные факты.
Что касается изменения форматов в будущем: если МВД добавит пятую цифру, букву или дефис, тип CHAR или VARCHAR мигрировать/расширить гораздо проще. А вот если вы заложились на INTEGER, то при появлении букв ваша схема просто ляжет с ошибкой типизации.
а вы считаете что эти теоретические новые номера корректно хранить вместе со старыми? законом закреплён формат документа, если вводится новый формат - это будет новый закон и новый документ
вы же, наверное, не будете в колонку "номер паспорта гражданина РФ" писать, например, номер удостоверения моряка (хотя это тоже документ удостоверяющий личность)?
Даже если добавят пятую цифру, то скорее всего старые серии будут продолжать действовать. Скорее всего будут одновременно действовать 4 и 5-значные серии. Представляю какой взрыв мозга и толстый слой костылей ожидает тех, у кого числовой тип хранения)
Но зачем изначально создавать себе проблему на уровне хранения (терять данные)
В хранении bigint-ом нет никакой потери данных. Нет коллизий, из хранимого значения однозначно восстанавливается отображаемое значение и обратно. Так можно вообще заявить, что хранение дат timestamp-ом - это потеря данных.
чтобы потом героически её решать через View?
Хранение bigint-ом не требует никакого ощутимого оверхеда в части разработки и развития. Ну и суть подобного решения очевидна - это повышение производительности. Меня изначально смутило заявление, что по производительности индексов bigint и char(10) " разница практически нулевая ". Мой опыт, да и просто банальная логика говорит об обратном. Загрузить два значения в два регистра и сделать cmp гораздо быстрее, чем побайтово грузить строки и cmp их.
Меня это заинтересовало и я набросал простейший тест - инсёртим N номеров, ребилдим индекс, проверяем M номеров (90% существующих, 10% несуществующих). У меня получилось, что CHAR(10) минимум в полтора раза медленнее BIGINT и чем больше N, тем больше разница, конечно же.
TYPE ROWS SEARCHED AVG_MS (10 tries)
----------- ------------ ------------ ----------------------
BIGINT 500000 100000 825.813
CHAR(10) 500000 100000 1257.351
BIGINT 2000000 100000 1018.259
CHAR(10) 2000000 100000 1559.763
BIGINT 10000000 200000 2146.738
CHAR(10) 10000000 200000 3605.246Естественно, далеко не всегда нужно гнаться за этой производительностью, но с учётом того, что это практически ничего не стоит в части оверхеда, то BIGINT вполне себе жизнеспособный вариант, наряду с CHAR(10). А CHAR(10), например, будет быстрее в извлечении кусков серии, чем BIGINT.
если МВД добавит пятую цифру, букву или дефис, тип CHAR или VARCHAR мигрировать/расширить гораздо проще
То ваша схема просто ляжет с ошибкой транкейта и потребуется доработка физического хранилища.
А вот если вы заложились на INTEGER, то при появлении букв ваша схема просто ляжет с ошибкой типизации.
То есть потребуется доработка физического хранилища.
А вот если МВД добавит пятую цифру в серию (что гораздо вероятнее, чем букву), то в случае BIGINT потребуется только доработка представления, а в случае CHAR(10) - хранилища.
я правильно понимаю что "костылем" в данном случае вы называете, например, SQL-функцию LPAD ?
Если завтра поменяют формат в новых выдаваемых паспортах, например добавят ещё одну цифру спереди серии, то хранение данных с таким подходом очень сильно сядет в лужу.
Если завтра поменяют формат в новых выдаваемых паспортах
То и вариант схемы, предложенный автором, перестанет удовлеторять требованиям.
Ну там к варчару надо будет один символ добавить, не проблема, а вот отличить серию 0384 от 00384 в виде инта не получится.
так и не придется - серия имеет фиксированное число знаков, если теперь это 5 знаков - ок, значит 0384 теперь 00384
от того что к фиксированной длине добавили разряд формат не стал предполагать вариативность в длине
А в выданных паспортах нолик дорисуется сам или нужно будет в ФМС записываться?
если конкретно про паспорта то ни то ни другое - другой формат номера это другой документ
для ситуаций инвентарных номеров и т.п. при смене формата пишут что-то вроде "при указании номера меньшей длины считать номер дополненным нулями слева до <число> знаков"
Вы сами себе противоречите. Если другой формат это другой документ, то серия 0384 в базе не должна превратиться в 00384, т.к. это разные документы.
Если мы обсуждаем конкретно паспорта то да, новый формат номера это новый документ, и с моей точки зрения хранить его номер там же где хранятся номера "старых" документов неверно.
Вариант для менее бюрократизированных случае я привел как пример, как в некоторых случаях могут работать с номерами, для основного документа удостоверяющего личность это неприминимо.
А в выданных паспортах количество символов останется тем же до замены документа. 0384 и 00384 это две разные серии
А если букву?
Паспортные данные (серия, номер, дата выдачи, орган выдачи) должны храниться точно в том формате, в котором они представлены в документе, без потери ведущих нулей или других преобразований. Регулируется ст.5 фз-152, в случая аудита ПДн обрезания не лучший вариант
Вопрос больше в цели, если производительность критична и эффективность хранения, можно и в int на самом деле хранить, в тотже ch это будет эффективней, но с практичной точки зрения такой формат для расположения "рядом", т.е. фактически помимо pass_serial char(4), pass_number char(6) можно и в passport_data int(11)
з.ы. по сабжу автору статьи, не знаю причем тут тест на синьора, будучи еще зеленым мидлои при первой практике с номерами телефонов мне стало очевидно что это совсем не про тип номерной в строчный. скорее тут тест больше на теоретиков и тех кто ручками пощупал что это такое
А я после прочтения заголовка предвкушал жесть, как с адресами. Какие-нибудь легаси форматы, поддержка международных форматов, а что если добавятся буквы, не обязательно латиницей, нормализация и всё в таком роде
как с адресами
или временем...
Адреса - это вообще прекрасная тема. Я раньше занимался OCR визиток, составлял в т.ч. сводки характерных особенностей (жаль, заметки не сохранил, можно было бы статью хорошую сделать).
Там мало того, что форматы разные, есть целые сущности специфические. Например, где-то принято указывать название комплекса или кластера, где офис располагается. У нас тоже часто пишут "Сколково", скажем, но там это настолько системно, что нужно отдельное поле, выделяемое по ключевому слову.
В Таиланде, кстати, так и принято, что надёжнее дать название здания. Ведь адрес либо дублируется по 5-10 раз в пределах города, либо указывает на что-то другое, либо вообще не выдаёт результатов - причём один и тот же адрес может демонстрировать любое поведение от приложения к приложению. Поэтому уникальное название здания надёжнее.
А я после прочтения заголовка предвкушал жесть, как с адресами.
С адресами — х... х... словом, с адресами вовсе не хорошо.
Я думал, подвох в том, что серию правильно дробить на два блока по два символа, чтобы регион выдачи было проще вытягивать (и, например, делать внутреннюю верификацию с выдавшим подразделением))
Определять регион выдачи по серии - плохая затея.
От места выдачи моего паспорта до региона из первых двух цифр его серии больше полутора тысяч километров.
Могут ли выдать паспорт в посольстве в другой стране?
если длина фиксирована, что здесь как раз так
Когда имеешь дело с МВД РФ, это далеко не так. Посмотрите хотя бы на автомобильные номера.
Чиновники и депутаты вообще часто не умеют в IT. Поэтому придумывают неуникальные ИНН и т.п. баги, которые потом долго и нудно исправляют (если вообще исправляют).
Это вообще один из недостатков статьи.
Номера не просто имеют какой-то фиксированный формат, они его имеют НА ТЕКУЩИЙ МОМЕНТ ВРЕМЕНИ. То есть если заложиться на некий формат, то в произвольный момент в будущем приложение имеет все основания превратиться в тыкву. Упомянутые вами номера АМТ - это как раз наглядная демонстрация такого факапа, который уже имел место быть. Но только умные учатся на чужих ошибках.
И эта опасность в принципе не то что не рассматривается, но даже и не озвучивается.
А чем отличаются номера АМТ ?
А тем, что их формат как раз в один прекрасный момент взял, да и изменился. Что примечательно - вот совершенно без каких-либо вменяемых причин.
В прошлом тоже не всё гладко, мой старый паспорт имел серию типа XXII-НА, такое в цифры не запихнёшь, как ни крути.
В реальном проекте для одного из мобильных операторов использовалось хранение паспортов в специально заточенной для того системе, с валидацией, вычисткой, блэкджеком и далее по тексту.
У автомобильных номеров есть ещё одна подстава: они могут совпадать.
То есть в России могут существовать наборы одинаковых (по символам) номеров, но при этом один номер висит на тракторе (тип 3), второй на мотоцикле (тип 4), а третий на военной машине (тип 5). Поэтому разная длина - это меньшая из проблем.
Не тот ли это случай, когда собеседующий ждёт единственно верный ответ, который придумал сам?
Именно он. Судя по статье (не знаю как в реальности), задающий вопрос ожидает два исхода - либо правильный, либо неправильный. И даже не думает о том, что решение задачи сильно зависит от контекста и каждое решение имеет как определённые недостатки, так и свои преимущества. Вместо того чтобы разобраться в том, как оппонент думает и строит гипотезы, вопрошающий просто ожидает одного из двух ответов.
Единственный "исход", который я ожидаю – что разработчик умеет думать о природе данных.
Расскажите, в каком таком контексте потеря данных (ведущего нуля) – это не баг, а допустимый недостаток, у которого есть свои "преимущества"? Экономия 2 байт на жестком диске в обмен на невалидные паспорта пользователей? Отличный трейд-офф, заверните два.
До тех пор пока ведущий ноль не является значимым - тип данных для хранения никакой роли не играет. Ни varchar ни number не порождают баг сами по себе.
Если ваша команда забыла про обработку ведущих нулей в number - никто не мешает забыть ей про обработку пробелов в varchar, породив ровно такой же баг.
Можно придумывать какие угодно оправдания, смыслы и семантику - выбранный вами ответ не станет от этого единственно верным.
Да почему вот прямо невалидные? Это вопрос представления, а не валидации!
0001 и 1 это эквивалентные данные, при условии, что число состоит всегда из 4 знаков!
Если мы исходим из того, что количество цифр в серии может быть не 4 значным, а иным, то да, соглашусь.
Но не стоит забывать про фильтр данных на входе, что значения всех символов во входящих данных должны быть от 0 до 9
На самом деле отчасти вам отчасти правильно сказали.
Вы совсем позабыли сказать, а как этот номер паспорта дальше будет использоваться.
Может быть мне вообще будет лучше его хэшировать, чтобы не хранить "персональные данные".
А если это софт для паспортного стола - то разбить номер на сегменты для поиска. Или вообще свой тип данных создать.
А есть ещё советские паспорта, там всё немного по-другому)
Действующих уже нету, так что если система оперирует не архивными данными, а текущими - в целом, можно не заморачиваться.
Но так-то строка и там вполне сгодится, только верификация чуть сложнее будет.
А есть ещё и иностранные! Наверняка там и буквы попадаются, и дефисы, и вообще всё, что в голову придёт.
Отличное дополнение про иностранные и советские паспорта (возьму на вооружение в качестве дополнения, вопрос все же про паспорта РФ).
Это как раз тот самый «контрольный выстрел» в архитектуру, построенную на INTEGER.
Есть еще нюанс.
Никто и ни в какой стране не может предсказать какую-нибудь реформу, при которой в номере или серии паспорта неожиданно появятся буквы, изменится количество цифр, или еще что-то подобное не случится (например, решат, что номер паспорта для чего-то должен быть уникальным вне зависимости от серии, или серию вообще отменят, ибо лишняя сущность). При этом всегда будет переходный период, когда одновременно будут действительны документы и старого, и нового вида.
Потому я бы всегда для любых номеров документов в базу закладывал строковый тип без ограничений. А ограничения для предотвращения ошибок должен реализовывать интерфейс ввода данных (тем более, что его все равно надо реализовывать). Хотя я не специалист по базам данных, и может есть какие нюансы, требующие иного.
И кстати, кто знает, зачем в некоторых документах вообще серия? Какой сакральный смысл она несет? Традиция?
видимо на ваших собеседованиях размеры типов данных не спрашивают
всё-таки "целочисленный тип" некорректно подменять на integer, в него кажется ни в каком варианте исполнения все возможные 10-значные числа не влезут
Я почему-то ожидал подвох в том, что паспорта нельзя хранить в открытом виде (хз на самом деле, есть ли какие регуляции на этот счёт)
Мой ответ varchar, потому что я бы хранил персональные данные не в открытом виде в бд, а в зашифрованном. А там как правило строка или байты
База – SQL.
Что, простите?
Если это какая-то локальная БД, то наверняка лучше char(n), но если это большая БД, то при сравнении и поиске из большого массива карточек найти совпадающие числа быстрее, чем строки. А это скорость обработки.. причём кратно быстрее
А если паспорт поврежден/сожжен, от него остался только номер, а первая цифра залита чернилами/кровью/краской?
Если первая цифра утрачена в номере, то сравниваем с массивом из 10 значений. И собственно это в сравнении с обычным поиском это несколько более иной специализированный поиск. Для возникновения такой ситуации, нужно, чтобы от документа остался только клочок одного листа.
При выборе способа хранения данных нужно исходить из того, что мы с ними делаем и что возможно в будущем будем делать. Это и будет определять формат хранения информации, который можно и нужно оптимизировать под наши задачи. Конкретно для криминалистики лучше, наверное, дублировать БД в ином формате. И то если нужно очень часто выполнять такие действия, а в случае если эти случаи редки, то проще не усложнять и для разовых задач сделать костыли
Если коротко - не оптимизируйте там где это не просят, и не будете иметь головной боли. Извечная проблема новичков, которые изучили структуры/типы данных и не хотят "ударить в грязь лицом", боясь что их сочтут некомпетентными из-за слишком простого решения.
Хороший совет из всей статьи - не следует воспринимать идентификаторы как числа. Если вам не нужно выполнять математические действия - забудьте о числовых типах.
Это хорошо до тех пор пока числа не станут большими и их вдруг не станет миллиарды, и вдруг не потребуется их искать. И окажется что продакшн база разрослась и расходы на сервера стали веселыми.
Вообще это удивительно как половина комментаторов и автор статьи игнорируют объемы. Может для паспортов оверхед и будет всего (всего!) в два раза, но если мы начинаем хранить ещё всякие ИНН, телефоны, какие-нибудь внутренние идентификаторы и прочее - разница начинает наростать. Хранить гигабайт или сто гигабайт, чего бы выбрать… хмм…
А про возможные буквы - такое бывает, но обычно это что-то типа обозначения региона владельца. Оно, к слову, в енумы числовые тоже прекрасно пакуется.
Честно скажу, про ведущий 0 не подумал, но что хранить как строку сразу, обоснование - идентификатор, "а вдруг завтра буквы добавят или еще что".
Паспорт – это идентификатор. Это метка, уникально указывающая на документ.
Это в теории. Уникально оно только в рамках первичной базы МВД (надеюсь). А вот за её пределами - нет. Внезапно, может прийти юзер, который будет заявлять, что на самом деле это он владелец номера, с которым кто-то зарегался в вашей системе пару месяцев назад.
У чисел в паспорте есть семантика, и вы вполне можете её использовать. Сортировать по региону, по году выпуска, к примеру.
Правильный ответ: зависит от целей и способа использования этих данных, в задаче это не описано.
Статья глупая.
Примеры теоретические, практически они бесполезны
Код региона в серии - это там где напечатан бланк паспорта. Я прописан в области, код по серии - Москва
Паспорт получен в 2024, но год выпуска бланка в серии - 23, т.к. бланки были напечатаны с запасом, и не все использованы в 23-м
Есть серии, которые вне правил, типа паспортов выданных в Крыму или в консульствах за пределами РФ
И что? Вы сами подтверждаете, что у частей номера есть семантическое значение. Допустим, меня интересует обработка "регионов, в которых напечатан паспорт", что дальше? Хранить их в переводе на немецкий? В римских цифрах?
Таким образом, способ хранения опять зависит от решаемых задач. Если честно, это настолько очевидное утверждение, что я не понимаю, о чем тут можно спорить,если не задаться целью спорить.
Претензии же к "теоретичности" в контексте собеседования (а статья про собеседование) вообще вызывают недоумение. Разумеется, это теоретический пример, а что же это ещё можно обсуждать на собеседовании, продуктовое решение?
Минутка повышения самомнения) сразу ответил строка. Sql не знаю от слова совсем, зато много работаю в связке qwery pivot excel. И опыт не определить тип данных а потом матерится от не правильного поведения учит - число только для того что будешь умножать
Открыл коробочку и добавил в неё Вашу статью
«Всё не так плохо, как вам кажется. Всё гораздо, ГОРАЗДО хуже!» ©
http://krylov.livejournal.com/3450110.html
Вот вам ещё в коробочку
Как бывший владелец паспорта СССР ржал в голос услышвв про number в любой его реинкарнации. XVI ИВ и 6 цифр,
А ещё есть прикол со свидетельством о рождении: "серия свидетельства о рождении вводится в формате: римская цифра (латинскими буквами I, V, X), дефис (или без него) и две буквы кириллицы (например, II-АВ или IIАВ), далее — 6 цифр номера. Римские цифры (I, V, X) вводятся в английской раскладке, а буквенная часть — в русской. ".
То есть IV-ак и IV-ak это разные документы, написал строчными для наглядности.
"серия свидетельства о рождении вводится в формате: римская цифра (латинскими буквами I, V, X), дефис (или без него) и две буквы кириллицы (например, II-АВ или IIАВ), далее — 6 цифр номера.
А у меня у паспорта (советского) номер по такой же схеме был. Кстати, римская цифра может состоять из четырёх символов (VIII — это цифра 8)!
VIII — это цифра 8
Это число 8, записанное несколькими цифрами. И, наоборот, цифра X означает число 10 (в десятичной системе счисления).
Это число 8, записанное несколькими цифрами.
Римское — число, а арабская — цифра.
С чего бы?
Цифры (в русском языке) - это знаки, которыми записываются числа. Вот, например, определение из математического словаря:

Ответ навскидку: строка
Ответ подумавши. Никто не сказал, что номер паспорта всегда будет выглядеть, как "NN NN NNNNNN". Количество знаков в каждом "поле" может измениться. Количество полей может измениться. Допустимый алфавит может измениться (сейчас он состоит только из цифр, но никто не обещал, что это навсегда).
Будет нехорошо, если гос-во изменит формат номеров паспортов, и паспорта старого типа будет невозможно хранить в базе вместе с новыми.
И как выше уже отметили, бывают паспорта, выданные другими государствами, и там могут быть свои особенности.
Поэтому, наверное, всё же строка, но в URI-образном формате: "scheme:identifier". Для каждой схемы - свой порядок преобразования символов из бумажного документа в символы в базе. Например, можно договориться, что современные российские паспорта хранятся в виде "NNNN NNNNNN", без пробела между половинками серии и с одним пробелом между серией и номером.
Заодно схема образует namespace, и мы не сравним случайно номер армянского паспорта с номером паспорта из Мозамбика - кто знает заранее, вдруг у них одинаковый формат и номера могут совпасть?
Ну и эта. Есть смысл посмотреть, нет ли на эту тему международных стандартов каких. А то вдруг мы еще чего не учли...
Прежде чем читать дальше – ответьте себе честно. Прямо сейчас. Какой тип?
i64.
Номер моего паспорта выглядит как xx xx xxxxxx. Надо полагать, если разделили номер на серию из двух частей и номер без серии, тут, возможно, есть какая-то семантика, так что будем хранить по отдельности:
• Байт под первый xx
• Байт под второй xx
• (log(2, 1e6) ≈ 24) / 8 = 3 байта под xxxxxx
Итого пять байт. К ним нужен хедер. Первый байт пусть будет номером версии номера паспорта, а ещё два (для круглости) — размер в байтах (пусть будет остальной части, а не всего — я всегда делаю остальной части, чтобы не терять впустую несколько байт — мелочь, а приятно). Итого 8 байт, которые не надо специально выравнивать в памяти.
Когда в будущем в номере паспортов появятся посконно-домотканные Ё, Ъ и Ж (вариант для хипстеров-оптимистов: ❤️, 😎 и 🐈), софт переписывать не придётся, поскольку хедер это всё поддерживает. Он вообще поддерживает 256 ревизий паспортной системы и номера паспортов размером до 64 килобайт.
Для начала в SQL DB можно хранить их 64-разрядным числом, а по мере необходимости перейти на BLOB'ы.
Проблема первая: ведущий ноль
Паспорт серии 0306 и паспорт серии 306 – это юридически разные документы
Структура намекает нам, что серии 306 не существует. Мы же ничего не зная гадаем по имеющимся данным, не так ли? Чтобы показать свои способности? Может, я и не прав насчёт серии 306, но тогда давайте спецификацию номера паспорта, и запишем её в Джиру, чтоб потом не говорили, что плохой разработчик всего не предусмотрел. Если выяснить спецификацию номера это самостоятельная задача — нет проблем, но сначала напишем в Джиру задачу найти спецификацию номера. Как показывает практика, сегодня тебе говорят: поддержи хоть как-нибудь вот этот симпатичный девайс, а через полгода, когда вылезает какой-нибудь баг с протоколом обмена, очень удивляются, когда ты показываешь тикет, resolved as: «Мне пришлось взломать Пентагон, чтобы найти вот этот кусок PDF'ки на китайском — другой документации я не нашёл, ведь вы же зажали 10$ за подписку на техподдержку производителя».
Паспорт – это идентификатор. Это метка, уникально указывающая на документ. Над идентификаторами не производят математических операций. Их сравнивают на равенство, ищут по ним, передают – и всё.
Да ну? А зачем тогда ввели эту самую серию? Я мало что знаю о номерах, но живя тут всю жизнь, сильно подозреваю, что граждане бывают первого сорта, второго сорта, третьего сорта и такие как я. И куски серии (или всю серию) почти наверняка надо сравнивать с началом и концом диапазонов в судебном делопроизводстве, при выписывании штрафов с камер и т.д.
Так что, &, >> и >, <, == ждут ребят ))
Как много слов из-за такого пустяка. Ну не знает кандидат особенностей домена, ну узнает за пару дней. В конце концов вся идея сводится к фразе "идентификаторы храним только в строках", которую надо один раз сказать на онбординге, и человек будет знать и применять. А не сразу навешивать ярлыки "инженер"/"не инженер ".
У меня вот был противоположный кейс - идентификатор в некой системе является целым числом из 19 цифр. Именно числом, не строкой. Хорошо, что хоть всегда положительным. Система внешняя, заставить её перевести id в строку невозможно. И все бы хорошо, если бы не представление чисел в JavaScript - оно туда не лезет. Точнее, лезет, но округляется, т.к. под целые числа в JS отведено всего 53 двоичных разряда, а для хранения этого идентификатора нужны все 63. А округленный идентификатор - это идентификатор совсем другого объекта.
Вы правильно подметили, это проблема особенностей доменной области. Возможно имеет смысл сразу делать ремарку, что может начинаться с нуля, может кандидат никогда не видел номера паспортов.
У меня вот был противоположный кейс - идентификатор в некой системе является целым числом из 19 цифр.
Какой же это противоположный? Тот же самый. Сделали бы этот идинтификатор строкой, не было бы проблемы.
Иногда приходится выполнять поиск по неполным данным (например, доступна лишь часть номера паспорта). Поиск по вхождению в числовых данных - это ужос
Паспорт – это идентификатор. Это метка, уникально указывающая на документ.
Спасибо, поржал.
«Двойные паспорта» оказались на руках у десятков тысяч жителей Башкирии. Путаница возникла несколько лет назад, тогда случайно напечатали две партии документов с одинаковыми номерами. Но о проблеме многие владельцы недействительных документов узнают только сейчас. Например, когда нужно срочно снять деньги в банке или купить билет.
— Эти номера значатся сразу на двух людях!
То, что с его паспортом что‑то не так, Анатолий Кривобоков понял, когда ему отказались выдать в отделении банка его же деньги со сберегательного счета. Более того, заявили, что в базе он числится умершим. Пенсионеру посоветовали обратиться за разъяснениями в миграционную службу. Оказалось, что документ с точно таким же серийным номером по ошибке выдали и еще одному человеку.
«С моим номером человек умер. Я говорю: он умер, а я‑то живой. Но, когда решился я заменить свой паспорт, несмотря на все эти расходы, оказалось, что и бабуля моя похоронена заочно. Значит, уже надо два паспорта менять. И полторы тысячи платить! А паспорта — нормальные, на руках», — разводит руки Анатолий Кривобоков.
В итоге в миграционной службе собственную ошибку исправили. Паспорт менять не стали, а уже окончательно закрепили его номер за одним единственным Анатолием Кривобоковым. Выяснилось, что путаница началась в 2003 году, когда в республике выдавали паспорта со вкладышами на башкирском языке. И «Гознак» по оплошности отпечатал две партии документов с одинаковыми номерами — с вкладышем и без.
(Источник)
«Всё не так плохо, как вам кажется. На самом деле всё гораздо, ГОРАЗДО хуже!» ©
Пользовательские типы данных все еще нельзя создавать в SQL? Совсем язык не развивается.
Не знаю, как другие SQL, но мы, слоно... эээ... погонщики слонов могём в свои типы: https://postgrespro.ru/docs/postgresql/11/sql-createtype :)
мы храним в NVarChar(20) полет нормальный. Довольно странно конечно что есть люди которые предлагают число, этож номер документа, он не может быть числом.
Правильным ответом на этот вопрос кстати может быть - а фиг его знает, спрошу чатжпт (он тоже говорит строку использовать)
Еще надо не забывать что номер паспорта это PII и по-хорошему в открытом виду в базе его хранить нельзя. И тут сразу уходят вопросы про тип данных
Телефон varchar(20)
Не правильно. Российский номер это всегда 10 цифр. +7 и 8 - эквиваленты.
При записи отсекаем эти префиксы и всё, что не цифра. Записываем в базу 10 символов.
При выводе - имеем возможность отформатировать номер телефона.
Как показывает практика, пользователю нельзя доверять вводить номер телефона и сохранять его "как есть" - они туда пихают все, что можно. Регулярки тут не помогут, если на беке проверять. Только строгая санация до 10 символов.
Немного выше @Wesha открыл хорошую коробочку, рекомендую посмотреть.
А если коротко от себя:
Санировать ввод - прекрасная мысль. А вот захардкодить в схему БД ограничение «только Россия и только 10 цифр» – это классический legacy-капкан.
Ваше решение намертво привязывает бизнес к одной стране. Что произойдет, когда к вам придет клиент из Беларуси (+375) или Узбекистана (+998)? База с ограничением в 10 символов просто не даст ему зарегистрироваться.
Да и любой адекватный SMS-шлюз работает по международному стандарту E.164 (до 15 цифр, начиная с +). Если вы отрезали код страны, вам придется хардкодить +7 обратно при каждом обращении к API провайдера.
Что произойдет, когда
Вот когда произойдет, тогда и будем думать. Во многих случаях этого не произойдет НИКОГДА
На моей практике, это НИКОГДА случается постоянно. Завтра бизнес изменит решение и перенастроится на клиентов из других стран. Или решат продать решение в другую страну. И вам придётся лезть в базу, перенастраивать типы и проверять, что вся цепочка обработок отрабатывает корректно.
Зачем, если можно всё продумать заранее?
На моей практике, это НИКОГДА случается постоянно.
Если у коллеги это случалось НИКОГДА, то он просто коллега ещё юн и неопытен. Эх, если б вы знали, сколько НИКОГДОВ случилось в моей жизни... (горько плачет, бьётся головой об стену, уходит в запой.)
он просто коллега ещё юн и неопытен
43 года как юн. Давай ты не будешь тут про неопытность говорить?
Эх, если б вы знали, сколько НИКОГДОВ случилось в моей жизни
Предприятие работает много лет только с юр. лицами из РФ. Телефоны в базе хранятся как я описал выше. "Во многих случаях этого не произойдет НИКОГДА" - как я и писал. Нет, не было и не будет иных юр. лиц, кроме как из РФ.
Был бы ты такой умный и опытный, то знал бы, что во многих случаях случается именно НИКОГДА. И что не надо сходить с ума по построению идеальной модели хранения данных. С большей долей вероятности ПО будет жить именно в таком виде до конца дней существования своего предприятия.
Все верно. Надо отметить что подобные ошибки допускают вендоры. Инверсия переводила счета с цифр на строки.
То же справедливо в отношении PAN и CVV.
Varchar предпочтительнее char, могут быть ошибки в связи с лишними пробелами.
Условие задачи неполное.
Получив "правильный" ответ, поймёте только то, что человек думет также, как и Вы или нет. Но правильный ответ с данным условием любой.
А чтобы только тип char был единственным верным, нужно дополнить условие задачи. Указать,что-то типа: минимизировать вероятность багов, упростить изменения данных в будущем.
Здравствуйте! Спасибо за статью, было любопытно подумать. Хочу узнать что вы думаете о моем решении:
Первое что я подумал "Утечки персональных данных грозят большими штрафами" :) Потому я сразу размышлял что хранить в чистом виде номер будет ошибкой. Однако нужно давать возможность поиска, и сделать что-то в духе гомоморфных операций.
И тогда я решил, что нужно хранить данные в измененном виде. В качестве самой простой модификации добавиь repunit - число из единиц. Потому я выбрал целочисленный тип
Т.е. например серия 1234 номер 123456 превратились бы в 2345 23456. При этом зная алгоритм скрытия номера, можно было бы использовать repunit как модифицирующий ключ, для поиска в базе данных
Я не знал, что могут быть отедельно паспорта 0306 и 306, в целом никогда не видел в жизни номер начинающийся с 0, потому об этом не подумал. Но в моем решении это решается просто длиной repuinit, она должна быть тождественна длине серии+номеру. Т.е. для 306 и 0306 должно быть разное число единиц. Да возможно костыль, но если 0306 и 306 не возможны одновременно, даже он не требуется
Здравствуйте! Отличный рефлекс – думать о защите ПДн. Но остаются проблемы:
При утечке БД такой алгоритм разгадают за 5 минут, и от штрафов регуляторов (например, по 152-ФЗ) это самописное решение не спасет. Нужна реальная криптография, а там в любом случае необходимо хранить строку (могу ошибаться, в криптографии не силен).
Ваш кейс идеально подтверждает статью: вы выбрали INT именно ради математики, и это сразу всё сломало. 0306 + 1111 = 1417, а 306 + 111 = 417. Без отдельного хранения длины ключа вы не сможете расшифровать данные обратно. И тут начинается усложнение.
Что делать при переполнении разрядов с серией 0999? 999 + 1111 = 2110.
0-9 -> 1-10
00-99 -> 11-110
000-999 -> 111-1110
0000-9999 -> 1111-11110
Вполне однозначно отображает последовательности произвольной длины в числа, хотя конечно никакой криптографией тут и не пахнет
Ключ должен храниться не в базе, да он предполагается хотя бы в кэше, или в худшем случае хардкод в вашем сервисе, вплоть до персонального, с ним вычисляется сдвиг, преобразуясь в другое число в сервисе, и все ФИО тоже должны быть закодированны/зашифрованны. Поиск идет уже зашифрованым номером, со скоростью целочисленного сравнения, вместо построчного. При частом использовании должно быть быстрее, чем такая же операция посимвольно.. Таким образом сопоставить с данными людей не получится, хотябы, не зная полностью алгоритма и цифрового ключа. А так да, это не прям идеальное решение, но если скорость поиска и невозможность восстановления/сопоставления данных без знания 2х ключей в полной форме - невозможна. Есть интересные методы шифрования, которые маскируют энтропию информации в максимальную, с выравниванием по верхней границе можно, но на коротких данных, они менее заметный эффект оказывают, можно это делать по символу, или вычислять результат любой функцией, которая имеет обратную. Те репюнит был простейшим вариантом ключа, для понимания самой идеи хранить уже защищенное значение, это может быть просто какая то хэш функция малого размера, в обобщенном смысле, т.е. делать вычисление над номером, над фио, и при хранении и при поиске, при это целочисленная операция будетдешевле чем над строкой. Думаю на каком то масштабе запросов в секунды к БД мы сможем увидеть разницу. Интересно проверить, просто чтобы понимать есть ли ценность у такой идеи. Может разницы в скорости не будет, тогда конечно, можно строку как угодно шифровать. Я попробую попозже сделать эксперименты с заполнением базы и скорости поиска по мере ее наполненности, напишу сюда в коммент. Мне показалось это может быть удобной идеей и шифровать данные быстро и искать, потому я выбрал решение как выше масштабируемое. Я проверю, но напишу как время будет. Завтра понедельник, нужно поработать :) Я попробую сразу пару вариантов: хардкодный ключ в коде, персональный ключ в key-value кэше, и наполнять бд вплоть до всех возможных номеров пасспортов + разные функции, простое смещение, хэш функция, и другие симмитричные типо xor. Мне самому интересно и нужно, но для других значений, вроде дат рождений.
Сами данные в базах шифровать нет смысла. Это замедляет доступ и не несёт практической пользы.
Обычно шифруется вся база целиком, либо жесткий диск. Либо, можно замок повесить на серверную.
Я просто разрабатываю систему анализа речи и ряда сопутствующих функционалов, и у меня ни в брокере сообщений, ни в базе данных, ничего не хранится не зашифрованным :) Я никого не заставляю так делать, но себе просто позволить не могу иначе🥲Разве что есть детерменированные алгоритмы шифрования, где мне нужен поиск, и не детерменированные, где нужна выше защищенность корпоративных данных. Я зделаю замеры и отпишусь! Завтра нужно поработать, потом я сделаю замеры, у меня просто есть убежденность что моя модель будет быстрей и более масштабируемой при росте записей в бд. Определить значения я не могу но пока уверен, что будет быстрее, не смотря на шифрование, тк рассчет до запроса к бд и очень дешевый. Но может бд как то оптимизирует хэши, и быстрей не будет, я проверю чтобы знать, отпишусь.
Прежде чем читать дальше – ответьте себе честно. Прямо сейчас. Какой тип?
Никакой. Недостаточно информации для определения типа. Требования сначала описать надо. Не вижу их. Зачем вы меня спрашиваете об этом? Ходят тут всякие от работы отвлекают. Идите с аналитиком разбирайтесь, потом приходите с юз кейсами, ограничениямии, ф требованиями, неф требованиями и т.д. Ессно не на словах, у нас все по ieee.
Поэтому, исходя из вашего вопроса хранить можно как угодно, потому что никаких требований не представлено и любой вариант будет корректным.
Поправочка, минимальные требования все же есть это российский паспорт. Варчар точно подходит на вскидку, для оптимизации хранения сначала нужно изучать как он формируется источником. Но как и сказал ранее, т.к мы не знаем зачем нам эти номера и серии, хранить можно варчаром. Есть же стандартные вопросы: кто, зачем, почему, как долго, как часто, ну вы поняли.
Предварительная оптимизация это зло. Не делайте так. Заказчику может абсолютно плевать что поиск будет три часа, а то устроили тут индексы с блекджеком и предикты будущего.
Вопрос можно усложнить. Например, известно, что население России составляет от 138,8 до 145,5 млн человек. Ежегодно в России рождается около 1,2 млн детей. При этом, за 10 последних лет, от 5 до 6 млн иностранцев получили российское гражданство (включая присоединённые территории)
Вопрос: какой риск того, что 10 символов паспорта (серия + номер) не хватит для того, чтобы обеспечить каждого гражданина РФ в ближайшие 10 лет?
Разумеется, вопрос с несколькими подвохами.
В серии паспорта два знака региона, два знака года, при этом ни то, ни другое не обязано фактически соответствовать региону и году выдачи. У меня например паспорт серии 6310, но выдан он в 2011 году. Соответственно у нас каждый год миллион номеров на регион, или 100 миллионов на всю страну. Здесь стоит напомнить, что номер паспорта - это номер бланка, при замене по возрасту или утере используется новый номер, а старый выходит из обращения. Гражданину, если он доживает до 45 лет, нужно три номера, плюс запас на утери и смену ФИО (обычно при бракосочетании), итого ну в среднем раз в десять лет. В год нам нужно порядка 15 миллионов новых номеров (плюс иностранцы новые территории, ещё пара миллионов) при ёмкости года в 100 миллионов. То есть, даже если половина страны разом потеряет паспорта и захочет их поменять - в рамках года номеров хватит.
Вопрос: какой риск
Ставлю на крайне низкий, потому что запас примерно пятикратный, плюс всегда можно залезть в серии следующих годов - их там на 65 лет вперед припасено. Единственная возможность нехватки - каждый гражданин будет по несколько раз в год менять паспорт по утере или смене ФИО.
Ну вот вы все (или почти все) подвохи обнаружили. Например:
1. Смертность. Старый номер паспорта можно высвободить
2. Серия паспорта. Первые две цифры означают регион, вторая пара - год, когда напечатали бланк. И вот тут возникают перекосы. Например, в Москве будет больше людей, получающих паспорт чем, например, на Сахалине.
3. На сегодняшний день, включая присоединённые территории, в России 89 регионов. Из 100 возможных комбинаций, включая 00. Итого, 100 млн на всю страну в год (если учесть, что перекосы по населению регионов могут решать предоставлением других кодов регионам с высокой плотностью населения. 1 млн - это число возможных комбинаций номера (считая шесть нулей - блатной номерок).
4. Учитывая, что серия паспорта отражает год печати бланка, возникает вопрос: а можно ли переиспользовать старые серию и номер? При утрате паспорта, однозначно, нельзя. Иначе, злоумышленники могут воспользоваться чужим документом. Но, если, например, прошло пять или десять лет с момента замены документа, это теоретически возможно, поскольку паспорт будет выдан на другое имя и с другой датой.
Вот, наверное, только последнее рассуждение вы не до конца раскрыли. А так, первичный анализ верный. И, что интересно, этот ход рассуждения очень важен для разработчика. Ведь, выбирая тип данных в хранилище, мы предполагаем и масштабирование. Например, если у нас будет не паспорт, а другой цифровой идентификатор с длиной 6 символов (только цифры), но мы планируем через год получить 1,5 миллиона новых пользователей, то следует задуматься над тем, хватит ли нам этой длины?
1. Смертность. Старый номер паспорта можно высвободить
А потом приходишь такой в банк — а тебе и говорят: «Вас нет, Вы умерли».
Старый номер паспорта можно высвободить
За повторное использование уникальных идентификаторов следует бить лопатой, я считаю. У нас 10 миллиардов на 150-миллинную страну, хватит на ближайшие лет двести.
Первые две цифры означают регион, вторая пара - год, когда напечатали бланк.
Вообще да, но пока мы не закладываем (а насколько я знаю, оно не заложено) требование о том, что регион и год должны совпадать с регионом и годом выдачи - нам на это плевать, можем перекашивать как хотим.
Мелкое уточнение, комбинаций 88, т. к. у Байконура свой номер (судя по алфавиту задумывавшийся как "остальное", хотя последовательность там в целом запутанная и явно помнящая о многих слоях легаси), у Сириуса тоже (часть Сочи, выделена из Краснодарского края в отдельную федеральную территорию), а три "матрешечных" автономных округа идут по материнским областям https://руни.рф/Коды_субъектов_Российской_Федерации https://classinform.ru/okato/kod.html
Хороший вопрос и хороший ответ - позволяет отделить выпендрежных кодеров от инженеров, которые в первую очередь думают про бизнес проблему.
Не надо ничего придумывать. Надо делать максимально просто и прозрачно. Сегодня номер паспорта только с цифрами, завтра надо будет хранить букву номера, послезавтра суверенный ИТ ГОСТ заставит хранить в паспорте какой-нибудь буквенный префикс, послезавтра это все будет не надо. Поэтому, надо делать просто
Ого, а я и не знал, что кому то приходит в голову запихивать чувствительные данные в int. Просто боюсь представить, что за ад потом начинается с экспортами, импортами и различными синхронизациями.
Строка. Я не то что не сеньор, вообще ни разу программистом себя не считаю, пишу для себя, в основном обработка данных по работе. Но на эти грабли наступать приходилось, так что всё, что не число - то не число. На всякий случай.
Вопрос со звездочкой - в каком виде хранить дату? А в проекте "ленты времени" для школьников (которая и про динозавров тоже)?
Если такие простые и очевидные вопросы вызывают м-м-м... затруднения у будущих "девелОперов", то у меня плохие новости
Не понимаю откуда берутся эти сеньоры. Если правильное проектирование базы это залог успеха в будущем.
Числа-не числа, операции арифметические… все проще: система нумерации паспортов это внешняя по отношению к вам система, причем настолько внешняя, что люди «разрабатывающие» ее о вашем существовании и не знают. Соответственно, они могут в любой момент могут сделать с ней что угодно. И ваш софт от этого не должен сломаться. Тут как бы и вариантов кроме строк особо нет. Добавят завтра буквы в номер паспорта, что вы делать будете с числами в базе?..
Тест для «сеньора»: в каком типе данных хранить номер паспорта?
Если у вас это "тест для синьора", то затрудняюсь даже представить, какой у вас "тест для джуна". Что он на собеседовании хотя бы не мычит, не ссытся под себя и не пускает слюну изо рта?
Тема почти раскрыта и как вопрос на собеседовании для сеньора пункт отличный.
Для хранения в БД однозначно строка. И лучше переменной длины, а то всякое случается. Можно придумывать, что лилирующий 0 можно вставить на лету из целого, но простой аргумент, что у всех строка не просто так и врят ли все они глупее тебя уже достаточен. Показывает и насмотренность и адекватность.
Дальше возможны варианты. Например, варианты как сжать ИНН, если с памятью совсем туго и сколько ты на этом реально сэкономишь на заданных объёмах.
"Вы проектируете базу данных. В ней нужно хранить серию и номер российского паспорта. Какой тип данных выберете? База – SQL. "
это вопрос из разряда
"Вы проектируете файловое хранилище. Как будете писать?"
руками.
Если вы вознамерились продемонстрировать глубокие познания, лучше начать с хорошей постановки задачи, в противном случае это уже негативно характеризует вас, как руководителя или ведущего специалиста.
Хммм... статья натолкнулся на множество размышлений:
Кто такой джун, мидл и сеньор давайте попробуем поразмыслить в рамках рассуждения автора.
Джун работает в рамках технического задания на разработку и он не может мыслить шире ТЗ.
Мидл же может мыслить шире он начинает пытаться охватывать проект.
Сеньор как правило мыслить глобально - межпроектные размышления.
Что это даёт джун - изучает тз и кодит строго по нему.
Мидл изучает тз и документы по проекту, Сеньор еще изучает предметной область, он пытается понять межпроектные пересечения внутри компании и пытается их учесть при кодинге...
Что дает предметной область - нормативные документы допустим ГОСТ, стандарты, ФЗ и пр. бумага - то что ранее серия и номер паспорта содержали буквы, а сейчас цифры, также что такое паспорт - документ удостоверяющий личность, а какие документы удостоверяющий личность еще в ходу?, а какие плановые изменения нормативки, наша ИС будет ли иметь интеграцию с внешними системами, а та какие требования и т.д. и т.п.
Автор не поднял эти вопросы, что наталкивает на мысль, что он в лучшем случаи младший мидл... к этому наталкивает упоминание о примере с его паспортом - "попробовал" - Сеньор не пробует, он руководствуются в первую очередь нормативкой...К сожалению скорее всего компания в которой он собеседовал сеньоров потенциально потеряла квалифицированных кадров из-за виртуального потолка начального мидла... к сожалению такое сплошь и рядом...
з.ы.
Я не отношусь себя к Сеньору в указанной автором области т.к. давно не кодю)))
Автор, без обид! )
Хранить номер паспорта вообще не нужно. Может хэш от него хранить. Сейчас с этими персональными данными сплошной геморрой
Ура я сеньер. Кажется это задача не для сеньора. Серия это не число, это идентификатор, который содержит числа. Очевидно, что это строка.



Тест для «сеньора»: в каком типе данных хранить номер паспорта?