Чи існує стандарт для зберігання нормалізованих телефонних номерів у базі даних?


95

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

Редагувати: Просто для роз’яснення варіанту використання тут: Зараз я зберігаю номери в одному полі varchar, і залишаю їх так само, як їх ввів клієнт. Потім, коли номер потрібен коду, я його нормалізую. Проблема полягає в тому, що якщо я хочу запитати кілька мільйонів рядків, щоб знайти відповідні телефонні номери, це передбачає функцію, наприклад

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

що страшенно неефективно. Крім того, запити, які шукають такі речі, як код міста, стають надзвичайно складними, коли це лише одне поле varchar.

[Редагувати]

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


Сучасна відповідь на запитання тут - stackoverflow.com/a/51761170/968003 . Суть цього - використовувати RFC 3966 для зберігання та номер libphone для синтаксичного аналізу / перевірки.
Алекс Клаус,

Відповіді:


80

По-перше, за межами коду країни немає реального стандарту. Найкраще, що ви можете зробити, - це визначити за кодом країни, до якої нації належить певний номер телефону, та розглянути решту номера відповідно до формату цієї країни.

Однак, як правило, телефонне обладнання та подібне стандартизоване, тому ви майже завжди можете розбити даний номер телефону на такі компоненти

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

Можливо, ви також захочете зберегти ціле число окремо як текстове поле (з інтернаціоналізацією), щоб ви могли повернутися пізніше та повторно проаналізувати номери, коли речі змінюються, або як резервну копію на випадок, якщо хтось подасть неправильний метод для аналізу формату певної країни і втрачає інформацію.


1
Знаєте про будь-яку хорошу перевірку JavaScript, щоб спробувати перевірити це?
cmcculloh

6
E164 встановлює набагато суворіші обмеження довжини номерів: 1-3 для країн і максимальну довжину 15. Це не скоро зміниться, знаючи глобальну систему телефонії.
Багатий

Вказані вами довжини, як видається, згідно з ITU-T E.164 абсолютно неправильні. Було б корисно, якщо б ви могли розмістити посилання на стандартний документ, з якого ви отримуєте свою інформацію, або пояснити, чому E.164 не застосовується.
Абтін Форузанде

5
@Abtin - не кожна телефонна система відповідає ITU-T E.164. Переважна більшість із них це робить, і варто зважити вибір між дотриманням стандартів та вимкненням деяких людей або перевищенням того, що говорить стандарт, і прийняттям усіх. Зверніть увагу, що E.164 можна розглядати як підмножину наведеної схеми. Тим не менше, я вважаю, що найкращим форматом є той, який користувач точно ввів, а потім алгоритм синтаксичного аналізу при необхідності токенізує його, а не зберігає марковану форму у базі даних.
Адам Девіс,

1) Чи можна припустити, що всі міжнародні номери відповідають наявності компонентів CAE? 2) Чи можете ви припустити, що компонент С - це єдине, що відрізняється залежно від того, звідки ви телефонуєте. Наприклад, номер США 850-555-1234 має A = 850 та E = 555-1234, а потім C = 1, якщо набираєте номер із США, і C = 001, якщо набираєте номер з Великобританії. Точка, незалежно від того, звідки ви набираєте номер, A і E ніяк не динамічні, правильно?
AaronLS

55

ПОЦІЛОК - Я втомився від багатьох веб-сайтів США. У них є якийсь хитро написаний код для перевірки поштових індексів та номерів телефонів. Коли я набираю свою цілком дійсну норвезьку контактну інформацію, я виявляю, що досить часто її відхиляють.

Залиште це рядком, якщо у вас немає особливих потреб у чомусь більш просунутому.


Старий добрий nvarchar(42)з невеликою кількістю перевірки /^+?[0-9 -\.\(\)#*]{4,41}$/працює дуже добре!
SandRock,

Я згоден, але водночас не згоден. Як правило, ви хочете зробити щось із цим збереженим номером телефону, наприклад, показати його. Замість того, щоб йти цією дорогою, намагаючись проаналізувати його настільки, щоб відобразити його, як ви хочете, я волів би зберігати його в нормалізованому вигляді. Зараз я не кажу, що нам слід зайти так далеко, щоб накласти дужки навколо коду міста. Я кажу, що це всі цифри без тире і т. Д.
Мафін,

4
Я вважаю, що телефонні номери слід проаналізувати перед їх збереженням, щоб їх можна було перевірити та зберегти нормалізованим способом. Міжнародний аналіз та форматування телефонних номерів цілком можливий за допомогою googlei18n / libphonenumber .
Роел

21

Сторінка Вікіпедії на E.164 повинна розповісти вам все, що вам потрібно знати.


3
ні, цей стандарт просто визначає структуру телефонних номерів (вони складаються з трьох номерів), але він не визначає, як їх відображати та / або зберігати. Я сказав стандарт? Я мав на увазі Рекомендацію .
BlueWizard

8

Ось моя запропонована структура, я був би вдячний відгуку:

Поле бази даних телефону має бути varchar (42) у наступному форматі:

CountryCode - номер x розширення

Так, наприклад, у США ми могли б мати:

1-2125551234x1234

Це буде номер США (код країни 1) з кодом / номером (212) 555 1234 та розширенням 1234.

Виділення коду країни тире робить код країни зрозумілим для тих, хто переглядає дані. Це не є суворо необхідним, оскільки коди країн є " префіксними кодами " (ви можете читати їх зліва направо, і ви завжди зможете однозначно визначити країну). Але, оскільки коди країн мають різну довжину (на даний момент від 1 до 4 символів), ви не можете легко з першого погляду визначити код країни, якщо ви не використовуєте якийсь роздільник.

Я використовую "х" для відокремлення розширення, оскільки інакше насправді було б неможливо (у багатьох випадках) з'ясувати, яке це число, а яке розширення.

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

Чому я вибрав варчар (42)? Ну, по-перше, міжнародні телефонні номери будуть різної довжини, отже, і "var". Я зберігаю тире та "x", що пояснює "char", і в будь-якому випадку, ви не будете робити цілочисельну арифметику на телефонних номерах (мабуть), тому мало сенсу намагатися використовувати числовий тип . Що стосується довжини 42, я використав максимально можливу довжину всіх складених полів на основі відповіді Адама Девіса та додав 2 для тире та символу "х".


7

Шукайте E.164. В основному ви зберігаєте номер телефону як код, що починається з префіксу країни та необов’язкового суфікса АТС. Дисплей - це проблема локалізації. Також може бути здійснено перевірку, але це також проблема локалізації (на основі префіксу країни).

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

Існує досить багато інформації про ITU-T E.164, але це досить загадково.


6

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

Таким чином, усі дані у вашій базі даних є "чистими" та без форматування


4

Зберігання

Зберігайте телефони в RFC 3966 (наприклад +1-202-555-0252, +1-202-555-7166;ext=22). Основною відмінністю від E.164 є

  • Без обмеження довжини
  • Підтримка розширень

Щоб оптимізувати ефективність операцій перегляду, зберігайте телефон у національному / міжнародному форматі поруч із полем RFC 3966.

Не зберігайте код країни в окремому полі, якщо у вас немає серйозних причин для цього. Чому? Тому що ви не повинні запитувати код країни в інтерфейсі користувача.

Здебільшого люди заходять у телефони, коли їх чують. Наприклад, якщо локальний формат починатиметься з 0або 8, користувачеві буде неприємно робити перетворення числа в голові (наприклад, « Добре, не вводьте« 0 », виберіть країну та введіть решту, що людина сказала в цьому полі ").

Розбір

Google має вашу спину, і ви можете перевірити та проаналізувати будь-який номер телефону за допомогою їх бібліотеки libphonenumber . Є порти майже на будь-яку мову.

Тож нехай користувач просто вводить " 0449053501" або " 04 4905 3501" або " (04) 4905 3501". Інше інструмент розбере для вас все інше.

Подивіться офіційну демонстраційну версію , щоб відчути, наскільки це допомагає.


3

Можливо, зберігання розділів телефонних номерів у різних стовпцях, дозволяючи вводити порожні чи нульові записи?


3

Гаразд, отже, виходячи з інформації на цій сторінці, ось початок роботи з міжнародним валідатором телефонних номерів:

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


2

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


1

Я думаю, що вільний текст (можливо, varchar (25)) є найбільш широко використовуваним стандартом. Це дозволить використовувати будь-який формат, як внутрішній, так і міжнародний.

Я думаю, головним рушійним фактором може бути те, як саме ви запитуєте ці цифри і що ви з ними робите.


Це не відповідає суті питання, а саме стандартизувати вміст полів БД, щоб забезпечити унікальне узгодження. Як я можу переконатися, що коли я запитую номер телефону 800-555-1212, що він відповідає, чи може користувач ввести "(800) 555-1212", "+1.800.555.1212" або будь-яке інше еквівалентне значення? Ось ця проблема вирішується.
Irongaze.com

1

Я вважаю, що більшість веб-форм правильно вводять код країни, код міста, а потім решту 7 цифр, але майже завжди забувають дозволити введення розширення. Це майже завжди призводить до того, що я вимовляю гнівні слова, оскільки на роботі у нас немає портьє, і для мене потрібен мій номер #.


1

Я вважаю, що більшість веб-форм правильно вводять код країни, код міста, а потім решту 7 цифр, але майже завжди забувають дозволити введення розширення. Це майже завжди призводить до того, що я вимовляю гнівні слова, оскільки на роботі у нас немає портьє, і для мене потрібен мій номер #.

Мені довелося б перевірити, але я думаю, що наша схема БД схожа. У нас є код країни (може бути за замовчуванням для США, не впевнений), код міста, 7 цифр та розширення.


1

Що стосується зберігання стовпця вільного тексту, який відображає зручну для користувача версію телефонного номера, а потім нормалізовану версію, яка видаляє пробіли, дужки та розширює '+'. Наприклад:

Зручний для користувача: +44 (0) 181 4642542

Нормалізоване: 00441814642542


10
Для кого саме +44 (0) 181 4642542 призначений для дружби? Користувачі Великобританії, які можуть не знати, що робити з номером +44, якщо вони не звикли набирати номер за кордоном, або міжнародні користувачі, які не знатимуть, що повинні відмовитись від (0)?
Mark Baker

0

Я б вибрав поле вільного тексту та поле, яке містить суто цифрову версію телефонного номера. Я б залишив представлення телефонного номера користувачеві і використовував нормалізоване поле спеціально для порівняння телефонних номерів у програмах на базі TAPI або при спробі знайти подвійні записи в телефонному каталозі. Звичайно, це не заважає забезпечити користувача схемою введення, яка додає інтелектуальні дані на зразок окремих полів для коду країни (за необхідності), коду міста, базового номера та розширення.


0

Звідки ви берете телефонні номери? Якщо ви отримуєте їх з частини телефонної мережі, ви отримаєте рядок цифр, а також тип і план номера, наприклад

441234567890 тип / план 0x11 (що означає міжнародний E.164)

У більшості випадків найкраще зробити все, щоб вони були збережені такими, як вони є, і нормалізовані для відображення, хоча зберігання нормалізованих чисел може бути корисним, якщо ви хочете використовувати їх як унікальний ключ або подібний.


0

Зручний для користувача: +44 (0) 181 464 2542 нормалізований: 00441814642542

Значення (0) не є дійсним у міжнародному форматі. Див. Стандарт ITU-T E.123.

"Нормалізований" формат не був би корисним для читачів США, оскільки вони використовують 011 для міжнародного доступу.


0

Я використав 3 різні способи зберігання телефонних номерів залежно від вимог використання.

  1. Якщо номер зберігається лише для отримання людиною і не буде використовуватися для пошуку його, що зберігається у полі типу рядка, точно так, як його ввів користувач.
  2. Якщо в полі буде здійснюватися пошук, то будь-які зайві символи, такі як +, пробіли та дужки тощо, видаляються, а решта цифр зберігається в полі типу рядка.
  3. Нарешті, якщо номер телефону буде використовуватися комп’ютером / телефонною програмою, то в цьому випадку його потрібно буде ввести і зберегти як дійсний номер телефону, який можна використовувати в системі, звичайно, цей варіант є найважчим для кодування для.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.