Существует ли стандарт для хранения нормализованных телефонных номеров в базе данных? - PullRequest
89 голосов
/ 03 сентября 2008

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

Редактировать: Просто для пояснения варианта использования: в настоящее время я храню числа в одном поле varchar и оставляю их так же, как их вводил клиент. Затем, когда номер нужен по коду, я нормализую его. Проблема в том, что если я хочу запросить несколько миллионов строк, чтобы найти совпадающие телефонные номера, это включает функцию, такую ​​как

where dbo.f_normalizenum(num1) = dbo.f_normalizenum(num2)

, что ужасно неэффективно. Также запросы, которые ищут такие вещи, как код города, становятся чрезвычайно сложными, когда это всего лишь одно поле varchar.

[Изменить]

Люди сделали много хороших предложений, спасибо! В качестве обновления, вот что я делаю сейчас: я по-прежнему храню числа в точности так, как они были введены, в поле varchar, но вместо нормализации вещей во время запроса у меня есть триггер, который выполняет всю эту работу при вставке записей или обновленный. Таким образом, у меня есть целые или большие буквы для любых частей, к которым мне нужно выполнить запрос, и эти поля проиндексированы, чтобы запросы выполнялись быстрее.

Ответы [ 18 ]

75 голосов
/ 03 сентября 2008

Во-первых, кроме кода страны, нет реального стандарта. Самое лучшее, что вы можете сделать, - это узнать по коду страны, к какой стране принадлежит конкретный номер телефона, и обработать остальную часть номера в соответствии с форматом этой страны.

Однако, как правило, телефонное оборудование и подобные устройства стандартизированы, поэтому вы почти всегда можете разбить данный номер телефона на следующие компоненты

  • 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, что требует признания того, что, если это номер США, слишком много цифр (и вам может потребоваться полное представление для рекламы или других целей) и что в США буквы отображаются на цифры иначе, чем в Германии.

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

57 голосов
/ 03 сентября 2008

KISS - мне надоели многие американские веб-сайты. У них есть некоторый грамотно написанный код для проверки почтовых индексов и телефонных номеров. Когда я набираю свою совершенно действительную норвежскую контактную информацию, я обнаруживаю, что довольно часто она отклоняется.

Оставьте строку, если у вас нет особой нужды в чем-то более сложном.

21 голосов
/ 04 октября 2008

Страница Википедии на E.164 должна рассказать вам все, что вам нужно знать.

8 голосов
/ 04 ноября 2008

Вот моя предложенная структура, я буду признателен за отзыв:

Поле базы данных телефона должно быть varchar (42) в следующем формате:

CountryCode - номер x добавочный номер

Так, например, в США мы могли бы иметь:

1-2125551234x1234

Это будет представлять номер США (код страны 1) с кодом города / номером (212) 555 1234 и добавочным 1234.

Разделение кода страны тире делает код страны понятным для того, кто просматривает данные. Это строго не обязательно, поскольку коды стран являются « префиксными кодами » (вы можете читать их слева направо, и вы всегда сможете однозначно определить страну). Но, поскольку коды стран имеют различную длину (в настоящее время от 1 до 4 символов), вы не можете сразу определить код страны, если не используете какой-либо разделитель.

Я использую «x», чтобы отделить расширение, потому что иначе было бы невозможно (во многих случаях) выяснить, какой номер был, а какой - добавочным.

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

Почему я выбрал варчар (42)? Ну, во-первых, международные телефонные номера будут разной длины, отсюда и «var». Я храню тире и "x", так что это объясняет "char", и в любом случае вы не будете выполнять целочисленную арифметику на телефонных номерах (я полагаю), поэтому нет смысла пытаться использовать числовой тип , Что касается длины 42, я использовал максимально возможную длину всех добавленных полей, основываясь на ответе Адама Дэвиса, и добавил 2 для тире и «х».

7 голосов
/ 03 сентября 2008

Посмотрите E.164. Обычно телефонный номер хранится в виде кода, начинающегося с префикса страны и необязательного суффикса pbx. Дисплей - это проблема локализации. Проверка также может быть выполнена, но это также проблема локализации (на основе префикса страны).

Например, + 12125551212 + 202 будет отформатирован в локали en_US как (212) 555-1212 x202. Он будет иметь другой формат в en_GB или de_DE.

Существует довольно много информации о МСЭ-T E.164, но она довольно загадочная.

6 голосов
/ 03 сентября 2008

Мне лично нравится идея сохранить нормализованный номер телефона varchar (например, 9991234567), а затем, конечно же, отформатировать этот номер телефона, как вы его отображаете.

Таким образом, все данные в вашей базе данных «чистые» и не требуют форматирования

3 голосов
/ 04 октября 2008

Хорошо, поэтому, основываясь на информации на этой странице, вот начало проверки международного номера телефона:

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

3 голосов
/ 03 сентября 2008

Возможно сохранение разделов телефонного номера в разных столбцах, допускающих пустые или нулевые записи?

2 голосов
/ 09 августа 2018

Хранение

Храните телефоны в RFC 3966 (например, +1-202-555-0252, +1-202-555-7166;ext=22). Основное отличие от E.164

  • Нет ограничений по длине
  • Поддержка расширений

Для оптимизации производительности операций просмотра сохраните телефон в национальном / международном формате рядом с полем RFC 3966.

Не храните код страны в отдельном поле, если у вас нет серьезных причин для этого. Зачем? Потому что вы не должны спрашивать код страны в пользовательском интерфейсе.

В основном люди входят в телефоны так, как они их слышат. Например. если локальный формат будет начинаться с 0 или 8, пользователю будет неудобно выполнять преобразование чисел в голове (например, " OK, не вводите" 0 ", выберите страну и введите остальное, что сказал человек в этом поле").

Синтаксический

У Google есть ваша спина, и вы можете проверить и проанализировать любой номер телефона с помощью их библиотеки libphonenumber . Есть порты практически на любой язык.

Так что позвольте пользователю просто ввести «0449053501» или «04 4905 3501» или «(04) 4905 3501». Инструмент подсчитает все остальное за вас.

См. Официальную демонстрацию , чтобы понять, насколько это помогает.

2 голосов
/ 17 марта 2017

Стандарт для форматирования чисел: e.164 . Вы должны всегда хранить числа в этом формате. Вы никогда не должны разрешать добавочный номер в одном поле с номером телефона, они должны храниться отдельно. Что касается числовых и буквенно-цифровых, это зависит от того, что вы собираетесь делать с этими данными.

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