Существует ли стандарт для хранения нормализованных телефонных номеров в базе данных?
Что такое хорошая структура данных для хранения телефонных номеров в полях базы данных? Я ищу что-то достаточно гибкое для обработки международных номеров, а также что-то, что позволяет эффективно запрашивать различные части номера.
Редактировать: просто для пояснения варианта использования: я сейчас храню числа в одном поле varchar и оставляю их так же, как их вводил клиент. Затем, когда номер нужен по коду, я нормализую его. Проблема в том, что если я хочу запросить несколько миллионов строк, чтобы найти совпадающие номера телефонов, это включает в себя функцию, такую как
where dbo.f_normalizenum(num1) = dbo.f_normalizenum(num2)
что ужасно неэффективно. Также запросы, которые ищут такие вещи, как код города, становятся чрезвычайно сложными, когда это всего лишь одно поле varchar.
[Редактировать]
Люди сделали много хороших предложений здесь, спасибо! В качестве обновления, вот что я делаю сейчас: я по-прежнему храню числа в точности так, как они были введены, в поле varchar, но вместо нормализации вещей во время запроса у меня есть триггер, который выполняет всю эту работу, когда вставляются записи или обновленный. Таким образом, у меня есть целые или большие буквы для любых частей, которые мне нужно запросить, и эти поля проиндексированы, чтобы запросы выполнялись быстрее.
18 ответов
Во-первых, кроме кода страны, нет реального стандарта. Самое лучшее, что вы можете сделать, это узнать по коду страны, к какой стране принадлежит конкретный номер телефона, и обработать оставшуюся часть номера в соответствии с форматом этой страны.
Как правило, однако, телефонное оборудование и тому подобное стандартизированы, так что вы почти всегда можете разбить данный номер телефона на следующие компоненты
- C Код страны 1-10 цифр (сейчас 4 или меньше, но это может измениться)
- Код города (провинция / штат / регион), код 0-10 цифр (может потребоваться поле региона и поле области отдельно, а не один код города)
- E Обмен (префикс или переключатель) кода 0-10 цифр
- L номер строки 1-10 цифр
С помощью этого метода вы можете разделить номера, например, людей, которые могут быть близки друг к другу, потому что у них одна и та же страна, регион и коды обмена. С сотовыми телефонами это уже не то, на что вы можете рассчитывать.
Кроме того, внутри каждой страны существуют разные стандарты. Вы всегда можете зависеть от (AAA) EEE-LLLL в США, но в другой стране у вас могут быть обмены в городах (AAA) EE-LLL и просто номера строк в сельских районах (AAA) LLLL. Вам придется начинать сверху в дереве какой-то формы и форматировать их по мере поступления информации. Например, код страны 0 имеет известный формат для остальной части номера, но для кода страны 5432 вам может потребоваться проверить код города, прежде чем вы поймете остальную часть номера.
Вы также можете захотеть справиться vanity
числа, такие как (800) Lucky-Guy
, что требует признания того, что, если это номер в США, есть слишком много цифр (и вам может потребоваться полное представление для рекламы или других целей), и что в США буквы отображаются на цифры иначе, чем в Германии.
Возможно, вы также захотите сохранить полное число отдельно в виде текстового поля (с интернационализацией), чтобы вы могли вернуться позже и повторно проанализировать числа при изменении ситуации, или в качестве резервной копии на случай, если кто-то предоставит неверный метод для анализа формата конкретной страны. и теряет информацию.
KISS - я устаю от многих сайтов в США. У них есть некоторый грамотно написанный код для проверки почтовых индексов и телефонных номеров. Когда я набираю свою совершенно действительную норвежскую контактную информацию, я нахожу, что довольно часто она отклоняется.
Оставьте строку, если у вас нет особой потребности в чем-то более сложном.
Страница Википедии на E.164 должна рассказать вам все, что вам нужно знать.
Место хранения
Хранить телефоны в RFC 3966 (как +1-202-555-0252
, +1-202-555-7166;ext=22
). Основным отличием от E.164 являются
- Нет ограничений по длине
- Поддержка расширений
Для оптимизации производительности операций просмотра сохраните телефон в национальном / международном формате рядом с полем RFC 3966.
Не храните код страны в отдельном поле, если у вас нет серьезных причин для этого. Зачем? Потому что вы не должны спрашивать код страны в пользовательском интерфейсе.
В основном люди входят в телефоны, когда они их слышат. Например, если локальный формат будет начинаться с 0
или же 8
, пользователю было бы неприятно выполнять преобразование чисел в голове (например, "ОК, не вводите" 0 ", выберите страну и введите остальное из того, что человек сказал в этом поле").
анализ
У Google есть ваша спина, и вы можете проверить и проанализировать любой номер телефона с помощью их библиотеки libphone number. Есть порты практически на любой язык.
Так что пусть пользователь просто войдет0449053501
" или же "04 4905 3501
" или же "(04) 4905 3501
". Инструмент позаботится об остальном за вас.
Посмотрите официальную демоверсию, чтобы понять, насколько это помогает.
Вот моя предложенная структура, я буду признателен за обратную связь:
Поле базы данных телефона должно быть varchar(42) в следующем формате:
CountryCode - номер x добавочный номер
Так, например, в США мы могли бы иметь:
1-2125551234x1234
Это будет представлять номер США (код страны 1) с кодом города / номером (212) 555 1234 и добавочным 1234.
Разделение кода страны тире делает код страны понятным для того, кто просматривает данные. Это не является строго необходимым, поскольку коды стран являются " префиксными кодами" (вы можете читать их слева направо, и вы всегда сможете однозначно определить страну). Но, поскольку коды стран имеют различную длину (в настоящее время от 1 до 4 символов), вы не можете легко определить код страны, если не используете какой-либо разделитель.
Я использую "x", чтобы отделить расширение, потому что иначе было бы невозможно (во многих случаях) выяснить, какой номер был, а какой - расширением.
Таким образом, вы можете хранить весь номер, включая код страны и добавочный номер, в одном поле базы данных, которое затем сможете использовать для ускорения запросов, вместо того, чтобы присоединяться к пользовательской функции, как вы до сих пор мучительно делали,
Почему я выбрал varchar(42)? Ну, во-первых, международные телефонные номера будут разной длины, отсюда и "var". Я храню тире и "x", так что это объясняет "char", и в любом случае вы не будете выполнять целочисленную арифметику на телефонных номерах (я полагаю), поэтому нет смысла пытаться использовать числовой тип, Что касается длины 42, я использовал максимально возможную длину всех добавленных полей, основываясь на ответе Адама Дэвиса, и добавил 2 для тире и "х".
Посмотрите E.164. Обычно телефонный номер хранится в виде кода, начинающегося с префикса страны и необязательного суффикса pbx. Дисплей - это проблема локализации. Проверка также может быть выполнена, но это также проблема локализации (на основе префикса страны).
Например, +12125551212+202 будет отформатирован в локали en_US как (212) 555-1212 x202. Это будет иметь другой формат в en_GB
или же de_DE
,
Существует немало информации об ITU-T E.164, но она довольно загадочная.
Лично мне нравится идея сохранить нормализованный номер телефона varchar (например, 9991234567), а затем, конечно же, отформатировать этот номер телефона при его отображении.
Таким образом, все данные в вашей базе данных будут "чистыми" и свободными от форматирования.
Возможно, сохранение разделов телефонного номера в разных столбцах, с учетом пустых или пустых записей?
Итак, основываясь на информации на этой странице, мы начинаем с валидатора международного телефонного номера:
function validatePhone(phoneNumber) {
var valid = true;
var stripped = phoneNumber.replace(/[\(\)\.\-\ \+\x]/g, '');
if(phoneNumber == ""){
valid = false;
}else if (isNaN(parseInt(stripped))) {
valid = false;
}else if (stripped.length > 40) {
valid = false;
}
return valid;
}
Примерно на основе сценария с этой страницы: http://www.webcheatsheet.com/javascript/form_validation.php
Стандарт для форматирования чисел e.164, Вы должны всегда хранить числа в этом формате. Вы никогда не должны разрешать добавочный номер в одном поле с номером телефона, они должны храниться отдельно. Что касается числовых и буквенно-цифровых, это зависит от того, что вы собираетесь делать с этими данными.
Я думаю, что свободный текст (возможно, varchar(25)) является наиболее широко используемым стандартом. Это позволит использовать любой формат, будь то внутренний или международный.
Я думаю, что основным движущим фактором может быть то, как именно вы запрашиваете эти цифры и что вы делаете с ними.
Как насчет хранения столбца свободного текста, который показывает удобную для пользователя версию телефонного номера, затем нормализованную версию, которая удаляет пробелы, скобки и расширяет "+". Например:
Удобно: +44 (0) 181 4642542
Нормализовано: 00441814642542
Я считаю, что большинство веб-форм правильно учитывают код страны, код города, а затем оставшиеся 7 цифр, но почти всегда забывают разрешить ввод расширения. Это почти всегда заканчивает тем, что заставляет меня произносить гневные слова, потому что на работе у нас нет портье, и мне нужен мой доб.
Я считаю, что большинство веб-форм правильно учитывают код страны, код города, а затем оставшиеся 7 цифр, но почти всегда забывают разрешить ввод расширения. Это почти всегда заканчивает тем, что заставляет меня произносить гневные слова, потому что на работе у нас нет портье, и мне нужен мой доб.
Я должен был бы проверить, но я думаю, что наша схема БД похожа. У нас есть код страны (может быть по умолчанию США, не уверен), код города, 7 цифр и расширение.
Я хотел бы пойти на поле свободного текста и поле, которое содержит чисто числовую версию номера телефона. Я оставляю представление номера телефона пользователю и использую нормализованное поле специально для сравнения номеров телефонов в приложениях на основе TAPI или при попытке найти двойные записи в телефонном справочнике. Конечно, это не помешает предоставить пользователю схему ввода, которая добавляет интеллектуальные возможности, такие как отдельные поля для кода страны (при необходимости), кода города, базового номера и добавочного номера.
Откуда вы получаете номера телефонов? Если вы получаете их из части телефонной сети, вы получите строку цифр, тип номера и план, например,
441234567890 тип / план 0x11 (что означает международный E.164)
В большинстве случаев лучше всего хранить все как есть и нормализовать для отображения, хотя сохранение нормализованных чисел может быть полезно, если вы хотите использовать их в качестве уникального ключа или аналогичного.
Удобно для пользователя: +44 (0)181 464 2542 нормализовано: 00441814642542
(0) недопустимо в международном формате. См. Стандарт ITU-T E.123.
"Нормализованный" формат не будет полезен для американских читателей, поскольку они используют 011 для международного доступа.
Я использовал 3 разных способа хранения телефонных номеров в зависимости от требований использования.
- Если число хранится только для извлечения человеком и не будет использоваться для поиска, оно будет сохранено в поле строкового типа в точности так, как его ввел пользователь.
- Если в поле будет производиться поиск, любые дополнительные символы, такие как +, пробелы, скобки и т. Д. Удаляются, а оставшееся число сохраняется в поле строкового типа.
- Наконец, если телефонный номер будет использоваться приложением компьютера / телефона, то в этом случае его необходимо будет ввести и сохранить в качестве действительного номера телефона, используемого системой, этот вариант, разумеется, сложнее всего кодировать. за.