Czy istnieje standard przechowywania znormalizowanych numerów telefonów w bazie danych?

95

Jaka jest dobra struktura danych do przechowywania numerów telefonów w polach bazy danych? Szukam czegoś, co jest wystarczająco elastyczne, aby obsługiwać numery międzynarodowe, a także czegoś, co umożliwia wydajne przeszukiwanie różnych części numeru.

Edycja: aby wyjaśnić tutaj przypadek użycia: obecnie przechowuję liczby w jednym polu varchar i zostawiam je tak, jak wprowadził je klient. Następnie, gdy numer jest potrzebny przez kod, normalizuję go. Problem polega na tym, że jeśli chcę przeszukać kilka milionów wierszy, aby znaleźć pasujące numery telefonów, obejmuje to funkcję, taką jak

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

co jest strasznie nieefektywne. Również zapytania, które szukają rzeczy, takich jak numer kierunkowy, stają się niezwykle trudne, gdy jest to tylko jedno pole varchar.

[Edytować]

Ludzie podali tutaj wiele dobrych sugestii, dzięki! Jako aktualizacja, oto, co teraz robię: nadal przechowuję liczby dokładnie tak, jak zostały wprowadzone, w polu varchar, ale zamiast normalizować rzeczy w czasie zapytania, mam wyzwalacz, który działa, gdy rekordy są wstawiane lub zaktualizowany. Mam więc ints lub biginty dla wszystkich części, które muszę zapytać, a te pola są indeksowane, aby zapytania działały szybciej.

Eric Z Beard
źródło
Współczesna odpowiedź na to pytanie jest tutaj - stackoverflow.com/a/51761170/968003 . Istota tego - użyj RFC 3966 do przechowywania i libphonenumber do analizowania / walidacji.
Alex Klaus,

Odpowiedzi:

80

Po pierwsze, poza kodem kraju nie ma prawdziwego standardu. Najlepsze, co możesz zrobić, to rozpoznać po kodzie kraju, do którego kraju należy dany numer telefonu, i zająć się resztą numeru zgodnie z formatem tego kraju.

Generalnie jednak sprzęt telefoniczny i taki jest znormalizowany, więc prawie zawsze można podzielić dany numer telefonu na następujące elementy

  • C Kod kraju 1-10 cyfr (obecnie 4 lub mniej, ale to może się zmienić)
  • Kod obszaru (prowincja / stan / region) kod 0-10 cyfr (w rzeczywistości może być wymagane osobne pole regionu i pole obszaru zamiast jednego numeru kierunkowego)
  • E Wymień (prefiks lub przełącznik) kod 0-10 cyfr
  • L Numer linii 1-10 cyfr

Dzięki tej metodzie możesz potencjalnie oddzielić numery, na przykład znaleźć osoby, które mogą być blisko siebie, ponieważ mają ten sam kraj, obszar i kod wymiany. Z telefonami komórkowymi nie można już na to liczyć.

Ponadto w każdym kraju obowiązują różne standardy. Zawsze możesz polegać na (AAA) EEE-LLLL w USA, ale w innym kraju możesz mieć wymiany w miastach (AAA) EE-LLL i po prostu numery linii na obszarach wiejskich (AAA) LLLL. Będziesz musiał zacząć od góry w drzewie w jakiejś formie i sformatować je tak, jak masz informacje. Na przykład kod kraju 0 ma znany format reszty numeru, ale w przypadku kodu kraju 5432 może być konieczne sprawdzenie numeru kierunkowego, zanim zrozumiesz pozostałą część numeru.

Możesz także sobie poradzić vanity liczby, takie jak (800) Lucky-Guy, co wymaga uznania, że ​​jeśli jest to numer w USA, jest o jedną za dużo cyfr (i może być konieczne pełne przedstawienie do celów reklamowych lub innych) oraz że w Stanach Zjednoczonych litery są odwzorowywane na numery inaczej niż w Niemczech.

Możesz również zapisać cały numer osobno jako pole tekstowe (z internacjonalizacją), aby móc wrócić później i ponownie przeanalizować liczby, gdy sytuacja się zmieni, lub jako kopię zapasową na wypadek, gdyby ktoś przesłał złą metodę analizy formatu określonego kraju i traci informacje.

Adam Davis
źródło
1
Czy znasz jakąś dobrą weryfikację JavaScript, aby spróbować to sprawdzić?
cmcculloh
6
E164 wyznacza znacznie ostrzejsze ograniczenia długości numerów: 1-3 dla krajów i maksymalną długość 15. To się nie zmieni w najbliższym czasie, znając globalny system telefonii.
Rich
Podane długości wydają się całkowicie błędne, zgodnie z ITU-T E.164. Byłoby pomocne, gdybyś mógł zamieścić łącze do dokumentu norm, z którego czerpiesz informacje, lub wyjaśnić, dlaczego E.164 nie ma zastosowania.
Abtin Forouzandeh
5
@Abtin - nie każdy system telefoniczny jest zgodny z ITU-T E.164. Jednak zdecydowana większość z nich to robi i warto rozważyć wybór między zachowaniem zgodności ze standardami a zamknięciem niektórych osób lub wykraczaniem poza to, co mówi norma i akceptowaniem wszystkich. Zauważ, że E.164 można postrzegać jako podzbiór powyższego schematu. Mimo to uważam, że najlepszym formatem jest to, co użytkownik dokładnie wprowadził, a następnie algorytm analizowania tokenizuje go w razie potrzeby, zamiast przechowywać formularz w bazie danych.
Adam Davis
1) Czy można założyć, że wszystkie numery międzynarodowe są zgodne z posiadaniem komponentów CAE? 2) Czy możesz założyć, że komponent C jest jedyną rzeczą, która różni się w zależności od tego, skąd dzwonisz. Np. Numer amerykański 850-555-1234 ma A = 850 i E = 555-1234, a następnie C = 1, jeśli dzwonisz z USA i C = 001, jeśli dzwonisz z Wielkiej Brytanii. Chodzi o to, że niezależnie od tego, skąd dzwonisz, A i E nie są w żaden sposób dynamiczne, prawda?
AaronLS
55

KISS - Mam dość wielu amerykańskich witryn internetowych. Mają sprytnie napisany kod do weryfikacji kodów pocztowych i numerów telefonów. Kiedy wpisuję moje doskonale prawidłowe norweskie dane kontaktowe, okazuje się, że dość często są one odrzucane.

Pozostaw to jako ciąg znaków, chyba że potrzebujesz czegoś bardziej zaawansowanego.

Bjorn Reppen
źródło
Dobry stary nvarchar(42)z odrobiną walidacji /^+?[0-9 -\.\(\)#*]{4,41}$/działa bardzo dobrze!
SandRock,
Zgadzam się, ale nie zgadzam się jednocześnie. Zwykle chcesz coś zrobić z tym zapisanym numerem telefonu, na przykład wyświetlić go. Zamiast iść tą drogą i próbować przeanalizować go na tyle, aby wyświetlić go tak, jak chcesz, wolałbym przechowywać go w znormalizowany sposób. Teraz nie mówię, że powinniśmy posunąć się tak daleko, aby wymusić nawiasy wokół numeru kierunkowego. Mówię, że to wszystkie liczby bez myślników itp.
The Muffin Man
4
Uważam, że numery telefonów należy przeanalizować przed ich zapisaniem, aby można je było zweryfikować i zapisać w znormalizowany sposób. Międzynarodowe parsowanie i formatowanie numerów telefonów jest całkowicie możliwe dzięki numerowi googlei18n / libphonenumber .
Roel
21

Strona Wikipedii pod adresem E.164 powinna zawierać wszystko, co musisz wiedzieć.

Bogaty
źródło
3
nie, ten standard definiuje tylko strukturę numerów telefonów (składają się z trzech liczb), ale nie określa, w jaki sposób mają one być wyświetlane i / lub przechowywane. Czy powiedziałem standard? Miałem na myśli Rekomendację .
BlueWizard
8

Oto moja proponowana struktura, byłbym wdzięczny za opinie:

Pole bazy danych telefonów powinno mieć postać varchar (42) o następującym formacie:

Kod kraju - numer x rozszerzenie

Na przykład w USA moglibyśmy mieć:

1-2125551234x1234

Oznaczałoby to numer amerykański (kod kraju 1) z numerem kierunkowym / numerem (212) 555 1234 i numerem wewnętrznym 1234.

Oddzielenie kodu kraju myślnikiem sprawia, że ​​kod kraju jest jasny dla kogoś, kto przegląda dane. Nie jest to absolutnie konieczne, ponieważ kody krajów są „ kodami prefiksowymi ” (można je czytać od lewej do prawej i zawsze można jednoznacznie określić kraj). Ponieważ jednak kody krajów mają różną długość (w tej chwili od 1 do 4 znaków), nie można łatwo określić na pierwszy rzut oka kodu kraju, chyba że użyjesz jakiegoś separatora.

Używam znaku „x” do oddzielenia rozszerzenia, ponieważ w przeciwnym razie naprawdę nie byłoby możliwe (w wielu przypadkach) ustalenie, która jest liczbą, a która jest rozszerzeniem.

W ten sposób możesz przechowywać cały numer, w tym kod kraju i rozszerzenie, w jednym polu bazy danych, którego możesz następnie użyć do przyspieszenia zapytań, zamiast dołączać do funkcji zdefiniowanej przez użytkownika, tak jak dotychczas boleśnie .

Dlaczego wybrałem varchar (42)? Po pierwsze, międzynarodowe numery telefonów będą miały różną długość, stąd nazwa „zmienna”. Przechowuję myślnik i „x”, więc to wyjaśnia „znak”, a poza tym nie będziesz wykonywać arytmetyki całkowitoliczbowej na numerach telefonów (tak sądzę), więc nie ma sensu używać typu liczbowego . Jeśli chodzi o długość 42, użyłem maksymalnej możliwej długości wszystkich zsumowanych pól, na podstawie odpowiedzi Adama Davisa, i dodałem 2 dla myślnika i „x”.

niezamierzenie pozostawiono puste
źródło
7

Wyszukaj E.164. Zasadniczo przechowujesz numer telefonu jako kod zaczynający się od prefiksu kraju i opcjonalnego sufiksu pbx. Wyświetlacz jest wtedy problemem lokalizacji. Można również przeprowadzić walidację, ale jest to również problem z lokalizacją (na podstawie prefiksu kraju).

Na przykład + 12125551212 + 202 zostanie sformatowany w ustawieniach regionalnych en_US jako (212) 555-1212 x202. Miałby inny format w en_GBlubde_DE .

Jest sporo informacji o ITU-T E.164, ale są one dość tajemnicze.

jcoby
źródło
6

Osobiście podoba mi się pomysł przechowywania znormalizowanego numeru telefonu varchar (np. 9991234567), a następnie oczywiście formatowanie tego numeru w tekście podczas jego wyświetlania.

W ten sposób wszystkie dane w Twojej bazie danych są „czyste” i wolne od formatowania

Mike Fielden
źródło
4

Przechowywanie

Przechowuj telefony w RFC 3966 (na przykład +1-202-555-0252, +1-202-555-7166;ext=22). Główną różnicą w stosunku do E.164

  • Brak ograniczeń co do długości
  • Obsługa rozszerzeń

Aby zoptymalizować wydajność operacji przeglądania, przechowuj telefon w formacie krajowym / międzynarodowym obok pola RFC 3966.

Nie przechowuj kodu kraju w osobnym polu, chyba że masz ku temu poważny powód. Czemu? Ponieważ nie powinieneś pytać o kod kraju w interfejsie użytkownika.

Przeważnie ludzie wchodzą do telefonów, gdy je słyszą. Np. Jeśli format lokalny będzie zaczynał się od 0lub 8, denerwowałoby użytkownika dokonywanie transformacji liczb w nagłówku (np. „ OK, nie wpisuj„ 0 ”, wybierz kraj i wpisz resztę osoba powiedziała w tej dziedzinie ”).

Rozbiór gramatyczny zdania

Google jest za twoimi plecami i możesz zweryfikować i przeanalizować dowolny numer telefonu za pomocą jego libphonenumber biblioteki . Istnieją porty na prawie każdy język.

Pozwól więc użytkownikowi po prostu wpisać „ 0449053501”, „ 04 4905 3501” lub „(04) 4905 3501 ”. Narzędzie wykona resztę za Ciebie.

Zobacz oficjalne demo , aby przekonać się, jak bardzo to pomaga.

Alex Klaus
źródło
3

Być może przechowywanie sekcji numerów telefonów w różnych kolumnach, umożliwiając puste lub puste wpisy?

Thomas Owens
źródło
3

Ok, więc w oparciu o informacje na tej stronie, oto początek międzynarodowego walidatora numerów telefonów:

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;
}

Luźno oparty na skrypcie z tej strony: http://www.webcheatsheet.com/javascript/form_validation.php

cmcculloh
źródło
2

Standardem formatowania liczb jest e.164. Liczby należy zawsze przechowywać w tym formacie. Nigdy nie należy zezwalać na umieszczanie numeru wewnętrznego w tym samym polu z numerem telefonu, należy je przechowywać oddzielnie. Jeśli chodzi o wartości numeryczne i alfanumeryczne, zależy to od tego, co będziesz robić z tymi danymi.

Brian West
źródło
1

Myślę, że dowolny tekst (może varchar (25)) jest najczęściej używanym standardem. Pozwoli to na dowolny format, zarówno krajowy, jak i międzynarodowy.

Myślę, że głównym czynnikiem sprawczym może być to, jak dokładnie sprawdzasz te liczby i co z nimi robisz.

Don
źródło
To mija się z celem pytania, jakim jest standaryzacja zawartości pól DB w celu zapewnienia unikalnego dopasowania. Jak się upewnić, że podczas zapytania o numer telefonu 800-555-1212 pasuje, czy użytkownik może wpisać „(800) 555-1212”, „+1.800.555.1212” lub jakąkolwiek inną równoważną wartość? To jest wyzwanie, któremu się podjęto.
Irongaze.com
1

Uważam, że większość formularzy internetowych poprawnie dopuszcza kod kraju, numer kierunkowy, a następnie pozostałe 7 cyfr, ale prawie zawsze zapominam o zezwoleniu na wprowadzenie numeru wewnętrznego. To prawie zawsze powoduje, że wypowiadam gniewne słowa, ponieważ w pracy nie mamy recepcjonistki, a mój numer wewnętrzny # jest potrzebny, aby do mnie dotrzeć.

Aaron
źródło
1

Uważam, że większość formularzy internetowych poprawnie dopuszcza kod kraju, numer kierunkowy, a następnie pozostałe 7 cyfr, ale prawie zawsze zapominam o zezwoleniu na wprowadzenie numeru wewnętrznego. To prawie zawsze powoduje, że wypowiadam gniewne słowa, ponieważ w pracy nie mamy recepcjonistki, a mój numer wewnętrzny # jest potrzebny, aby do mnie dotrzeć.

Musiałbym sprawdzić, ale myślę, że nasz schemat bazy danych jest podobny. Posiadamy kod kraju (może to być domyślnie USA, nie jestem pewien), numer kierunkowy, 7 cyfr i numer wewnętrzny.

Thomas Owens
źródło
1

A co z przechowywaniem kolumny z wolnym tekstem, która wyświetla przyjazną dla użytkownika wersję numeru telefonu, a następnie znormalizowaną wersję, która usuwa spacje, nawiasy i rozwija „+”. Na przykład:

Przyjazny dla użytkownika: +44 (0) 181 4642542

Znormalizowany: 00441814642542

ColinYounger
źródło
10
Dla kogo dokładnie +44 (0) 181 4642542 ma być przyjazny? Użytkownicy z Wielkiej Brytanii, którzy mogą nie wiedzieć, co zrobić z +44, jeśli nie są przyzwyczajeni do wybierania numerów międzynarodowych, lub użytkownicy międzynarodowi, którzy nie wiedzą, że powinni porzucić (0)?
Mark Baker
0

Wybrałbym wolne pole i pole zawierające czysto numeryczną wersję numeru telefonu. Pozostawiłbym reprezentację numeru telefonu użytkownikowi i użyłbym znormalizowanego pola specjalnie do porównań numerów telefonów w aplikacjach opartych na TAPI lub podczas próby znalezienia podwójnych wpisów w książce telefonicznej. Oczywiście nie zaszkodzi dostarczenie użytkownikowi schematu wejścia, który dodaje inteligencję, jak oddzielne pola na kod kraju (jeśli to konieczne), numer kierunkowy, numer bazowy i rozszerzenie.


źródło
0

Skąd bierzesz numery telefonów? Jeśli pobierasz je z części sieci telefonicznej, otrzymasz ciąg cyfr oraz typ numeru i plan, np

441234567890 typ / plan 0x11 (co oznacza międzynarodowy E.164)

W większości przypadków najlepszym rozwiązaniem jest przechowywanie ich wszystkich w niezmienionej postaci i normalizowanie ich wyświetlania, chociaż przechowywanie znormalizowanych liczb może być przydatne, jeśli chcesz ich używać jako unikalnego klucza lub podobnego.

Mark Baker
źródło
0

Przyjazny dla użytkownika: +44 (0) 181464 2542 znormalizowany: 00441814642542

(0) nie jest ważne w formacie międzynarodowym. Zobacz normę ITU-T E.123.

„Znormalizowany” format nie byłby przydatny dla czytelników w USA, ponieważ używają oni 011 do dostępu międzynarodowego.

Dave piosenkarz
źródło
0

Użyłem 3 różnych sposobów przechowywania numerów telefonów w zależności od wymagań użytkowania.

  1. Jeśli numer jest przechowywany tylko w celu pobrania przez człowieka i nie będzie używany do wyszukiwania, jest przechowywany w polu typu ciąg dokładnie tak, jak wprowadził go użytkownik.
  2. Jeśli pole ma być przeszukiwane, wszelkie dodatkowe znaki, takie jak +, spacje i nawiasy itp. Są usuwane, a pozostała liczba jest przechowywana w polu typu łańcuchowego.
  3. Wreszcie, jeśli numer telefonu ma być używany przez aplikację komputerową / telefoniczną, to w takim przypadku musiałby zostać wpisany i zapisany jako ważny numer telefonu do wykorzystania przez system, ta opcja jest oczywiście najtrudniejsza do zakodowania dla.
Jimoc
źródło