Gibt es einen Standard zum Speichern normalisierter Telefonnummern in einer Datenbank?

95

Was ist eine gute Datenstruktur zum Speichern von Telefonnummern in Datenbankfeldern? Ich suche etwas, das flexibel genug ist, um internationale Nummern zu verarbeiten, und das es ermöglicht, die verschiedenen Teile der Nummer effizient abzufragen.

Bearbeiten: Nur um den Anwendungsfall hier zu verdeutlichen: Ich speichere derzeit Nummern in einem einzelnen Varchar-Feld und lasse sie so, wie der Kunde sie eingegeben hat. Wenn die Nummer dann vom Code benötigt wird, normalisiere ich sie. Das Problem ist, dass, wenn ich ein paar Millionen Zeilen abfragen möchte, um passende Telefonnummern zu finden, dies eine Funktion beinhaltet, wie z

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

das ist schrecklich ineffizient. Auch Abfragen, die nach Dingen wie der Vorwahl suchen, werden extrem schwierig, wenn es sich nur um ein einzelnes Varchar-Feld handelt.

[Bearbeiten]

Die Leute haben hier viele gute Vorschläge gemacht, danke! Als Update mache ich jetzt Folgendes: Ich speichere Zahlen immer noch genau so, wie sie eingegeben wurden, in einem Varchar-Feld, aber anstatt die Dinge zur Abfragezeit zu normalisieren, habe ich einen Auslöser, der alles erledigt, was beim Einfügen von Datensätzen funktioniert oder aktualisiert. Ich habe also Ints oder Bigint für alle Teile, die ich abfragen muss, und diese Felder sind indiziert, damit Abfragen schneller ausgeführt werden.

Eric Z Bart
quelle
Eine zeitgemäße Antwort auf die Frage finden Sie hier - stackoverflow.com/a/51761170/968003 . Das Wesentliche dabei ist: Verwenden Sie RFC 3966 für die Speicherung und libphonenumber für die Analyse / Validierung.
Alex Klaus

Antworten:

80

Erstens gibt es jenseits des Ländercodes keinen wirklichen Standard. Das Beste, was Sie tun können, ist, anhand der Landesvorwahl zu erkennen, zu welcher Nation eine bestimmte Telefonnummer gehört, und den Rest der Nummer gemäß dem Format dieser Nation zu behandeln.

Im Allgemeinen ist die Telefonausrüstung und dergleichen jedoch standardisiert, sodass Sie eine bestimmte Telefonnummer fast immer in die folgenden Komponenten aufteilen können

  • C Ländercode 1-10 Ziffern (derzeit 4 oder weniger, dies kann sich jedoch ändern)
  • Eine Vorwahl (Provinz / Bundesland / Region) mit 0 bis 10 Ziffern (möglicherweise möchten Sie tatsächlich ein Regionsfeld und ein Ortsfeld getrennt anstelle einer Ortsvorwahl).
  • E Austauschcode (Präfix oder Schalter) mit 0-10 Ziffern
  • L Zeilennummer 1-10 Ziffern

Mit dieser Methode können Sie möglicherweise Nummern trennen, sodass Sie beispielsweise Personen finden können, die möglicherweise nahe beieinander liegen, weil sie dasselbe Land, denselben Bereich und dieselben Umtauschcodes haben. Mit Handys können Sie sich jedoch nicht mehr darauf verlassen.

Darüber hinaus gibt es in jedem Land unterschiedliche Standards. Sie können sich immer auf eine (AAA) EEE-LLLL in den USA verlassen, aber in einem anderen Land haben Sie möglicherweise Austausch in den Städten (AAA) EE-LLL und einfach Leitungsnummern in den ländlichen Gebieten (AAA) LLLL. Sie müssen oben in einem Baum in irgendeiner Form beginnen und diese so formatieren, wie Sie Informationen haben. Beispielsweise hat die Landesvorwahl 0 ein bekanntes Format für den Rest der Nummer, aber für die Landesvorwahl 5432 müssen Sie möglicherweise die Vorwahl überprüfen, bevor Sie den Rest der Nummer verstehen.

Möglicherweise möchten Sie auch mit vanityZahlen wie umgehen (800) Lucky-Guy, bei denen erkannt werden muss, dass bei einer US-Nummer eine zu viele Ziffern vorhanden sind (und Sie möglicherweise eine vollständige Darstellung für Werbe- oder andere Zwecke benötigen) und dass in den USA die Buchstaben dem zugeordnet sind Zahlen anders als in Deutschland.

Möglicherweise möchten Sie die gesamte Nummer auch separat als Textfeld (mit Internationalisierung) speichern, damit Sie später zurückkehren und Nummern erneut analysieren können, wenn sich die Dinge ändern, oder als Backup, falls jemand eine schlechte Methode zum Parsen des Formats eines bestimmten Landes einreicht und verliert Informationen.

Adam Davis
quelle
1
Kennen Sie eine gute JavaScript-Validierung, um dies zu validieren?
cmcculloh
6
E164 legt viel strengere Grenzen für die Länge von Nummern fest: 1-3 für Länder und eine maximale Länge von 15. Dies wird sich in Kürze nicht ändern, wenn man das globale Telefoniesystem kennt.
Rich
Die von Ihnen angegebenen Längen scheinen gemäß ITU-T E.164 völlig falsch zu sein. Es wäre hilfreich, wenn Sie einen Link zu dem Standarddokument veröffentlichen könnten, aus dem Sie Ihre Informationen ableiten, oder erklären könnten, warum E.164 nicht gilt.
Abtin Forouzandeh
5
@Abtin - nicht jedes Telefonsystem entspricht ITU-T E.164. Die überwiegende Mehrheit von ihnen tut dies jedoch, und es lohnt sich, die Wahl zwischen der Einhaltung von Standards abzuwägen, einige Leute auszusperren oder über das hinauszugehen, was der Standard sagt, und alle zu akzeptieren. Beachten Sie, dass E.164 als Teilmenge des obigen Schemas angesehen werden kann. Trotzdem glaube ich, dass das beste Format das ist, was der Benutzer genau eingegeben hat, und dann einen Parsing-Algorithmus hat, der es bei Bedarf tokenisiert, anstatt das tokenisierte Formular in der Datenbank zu speichern.
Adam Davis
1) Kann man davon ausgehen, dass alle internationalen Nummern den CAE-Komponenten entsprechen? 2) Können Sie davon ausgehen, dass nur die C-Komponente unterschiedlich ist, je nachdem, von wo aus Sie wählen? Beispielsweise hat die US-Nummer 850-555-1234 A = 850 und E = 555-1234 und dann C = 1, wenn Sie aus den USA wählen, und C = 001, wenn Sie aus Großbritannien wählen. Unabhängig davon, von wo aus Sie wählen, sind A und E in keiner Weise dynamisch, richtig?
AaronLS
55

KISS - Ich habe viele der US-Websites satt. Sie haben einen geschickt geschriebenen Code, um Postleitzahlen und Telefonnummern zu validieren. Wenn ich meine perfekt gültigen norwegischen Kontaktinformationen eingebe, stelle ich fest, dass diese häufig abgelehnt werden.

Lassen Sie es eine Zeichenfolge, es sei denn, Sie haben einen besonderen Bedarf an etwas Fortgeschrittenerem.

Björn Reppen
quelle
Ein guter Alter nvarchar(42)mit ein bisschen Validierung /^+?[0-9 -\.\(\)#*]{4,41}$/funktioniert sehr gut!
SandRock
Ich stimme zu, aber nicht gleichzeitig. Im Allgemeinen möchten Sie mit dieser gespeicherten Telefonnummer etwas tun, z. B. sie anzeigen. Anstatt diesen Weg zu gehen und zu versuchen, es genug zu analysieren, um es so anzuzeigen, wie Sie es möchten, möchte ich es lieber auf normalisierte Weise speichern. Jetzt sage ich nicht, dass wir so weit gehen sollten, um die Vorwahl in Klammern zu setzen. Was ich sage ist, dass es alle Zahlen sind, keine Striche usw.
The Muffin Man
4
Ich bin der Meinung, dass Telefonnummern vor dem Speichern analysiert werden sollten, damit sie auf normalisierte Weise validiert und gespeichert werden können. Das internationale Parsen und Formatieren von Telefonnummern ist mit der googlei18n / libphonenumber durchaus möglich .
Roel
21

Auf der Wikipedia-Seite zu E.164 finden Sie alles, was Sie wissen müssen.

Reich
quelle
3
Nein, dieser Standard definiert nur, wie Telefonnummern strukturiert sind (sie bestehen aus drei Nummern), gibt jedoch nicht an, wie diese angezeigt und / oder gespeichert werden sollen. Habe ich Standard gesagt? Ich meinte Empfehlung .
BlueWizard
8

Hier ist meine vorgeschlagene Struktur, ich würde mich über Feedback freuen:

Das Feld für die Telefondatenbank sollte ein varchar (42) mit dem folgenden Format sein:

CountryCode - Nummer x Nebenstelle

So könnten wir zum Beispiel in den USA haben:

1-2125551234x1234

Dies würde eine US-Nummer (Ländercode 1) mit der Vorwahl / Nummer (212) 555 1234 und der Nebenstelle 1234 darstellen.

Durch Trennen des Ländercodes mit einem Bindestrich wird der Ländercode für jemanden klar, der die Daten liest. Dies ist nicht unbedingt erforderlich, da Ländercodes " Präfixcodes " sind (Sie können sie von links nach rechts lesen und das Land immer eindeutig bestimmen). Da Ländercodes unterschiedliche Längen haben (derzeit zwischen 1 und 4 Zeichen), können Sie den Ländercode nur dann auf einen Blick erkennen, wenn Sie eine Art Trennzeichen verwenden.

Ich benutze ein "x", um die Erweiterung zu trennen, da es sonst (in vielen Fällen) wirklich nicht möglich wäre, herauszufinden, welche die Nummer und welche die Erweiterung war.

Auf diese Weise können Sie die gesamte Nummer einschließlich Ländercode und Nebenstelle in einem einzigen Datenbankfeld speichern, mit dem Sie Ihre Abfragen beschleunigen können, anstatt sich einer benutzerdefinierten Funktion anzuschließen, wie Sie es bisher schmerzhaft getan haben .

Warum habe ich einen Varchar (42) ausgewählt? Zunächst einmal werden internationale Telefonnummern unterschiedlich lang sein, daher die "var". Ich speichere einen Bindestrich und ein "x", so dass das "Zeichen" erklärt wird, und Sie werden ohnehin keine Ganzzahlarithmetik für die Telefonnummern durchführen (ich denke), daher ist es wenig sinnvoll, zu versuchen, einen numerischen Typ zu verwenden . Für die Länge von 42 habe ich die maximal mögliche Länge aller addierten Felder verwendet, basierend auf der Antwort von Adam Davis, und 2 für den Bindestrich und das 'x' hinzugefügt.

ungewollt leer gelassen
quelle
7

E.164 nachschlagen. Grundsätzlich speichern Sie die Telefonnummer als Code, der mit dem Länderpräfix und einem optionalen pbx-Suffix beginnt. Die Anzeige ist dann ein Lokalisierungsproblem. Die Validierung kann ebenfalls durchgeführt werden, es handelt sich jedoch auch um ein Lokalisierungsproblem (basierend auf dem Länderpräfix).

Beispielsweise würde + 12125551212 + 202 im Gebietsschema en_US als (212) 555-1212 x202 formatiert. Es hätte ein anderes Format in en_GBoder de_DE.

Es gibt eine Menge Informationen über ITU-T E.164, aber es ist ziemlich kryptisch.

jcoby
quelle
6

Ich persönlich mag die Idee, eine normalisierte varchar-Telefonnummer (z. B. 9991234567) zu speichern und diese Telefonnummer dann natürlich inline zu formatieren, während Sie sie anzeigen.

Auf diese Weise sind alle Daten in Ihrer Datenbank "sauber" und frei von Formatierungen

Mike Fielden
quelle
4

Lager

Speichern Sie Telefone in RFC 3966 (wie +1-202-555-0252, +1-202-555-7166;ext=22). Der Hauptunterschied zu E.164 sind

  • Keine Begrenzung der Länge
  • Unterstützung von Erweiterungen

Speichern Sie das Telefon im nationalen / internationalen Format neben dem Feld RFC 3966, um die Leistung von Ansichtsvorgängen zu optimieren.

Speichern Sie den Ländercode nicht in einem separaten Feld, es sei denn, Sie haben einen schwerwiegenden Grund dafür. Warum? Weil Sie auf der Benutzeroberfläche nicht nach dem Ländercode fragen sollten.

Meistens betreten die Leute die Telefone, wenn sie sie hören. Wenn das lokale Format beispielsweise von 0oder 8ausgeht, ist es für den Benutzer ärgerlich, die Zahlentransformation im Kopf vorzunehmen (z. B. " OK, geben Sie nicht '0' ein, wählen Sie das Land aus und geben Sie den Rest des Formats ein) Person sagte in diesem Bereich ").

Parsing

Google hat Ihren Rücken und Sie können jede Telefonnummer mithilfe der libphonenumber- Bibliothek validieren und analysieren . Es gibt Ports für fast jede Sprache.

Lassen Sie den Benutzer also einfach " 0449053501" oder " 04 4905 3501" oder " (04) 4905 3501" eingeben . Das Tool wird den Rest für Sie herausfinden.

Sehen Sie sich die offizielle Demo an , um ein Gefühl dafür zu bekommen, wie viel es hilft.

Alex Klaus
quelle
3

Vielleicht die Telefonnummernabschnitte in verschiedenen Spalten speichern, um leere oder Null-Einträge zu ermöglichen?

Thomas Owens
quelle
3

Ok, basierend auf den Informationen auf dieser Seite, hier ist ein Start für einen internationalen Telefonnummernprüfer:

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

Lose basierend auf einem Skript von dieser Seite: http://www.webcheatsheet.com/javascript/form_validation.php

cmcculloh
quelle
2

Der Standard für die Formatierung von Zahlen ist e.164 . Sie sollten Zahlen immer in diesem Format speichern. Sie sollten niemals die Nebenstellennummer im selben Feld wie die Telefonnummer zulassen, diese sollten separat gespeichert werden. Was numerisch oder alphanumerisch betrifft, hängt es davon ab, was Sie mit diesen Daten tun werden.

Brian West
quelle
1

Ich denke, Freitext (vielleicht varchar (25)) ist der am weitesten verbreitete Standard. Dies ermöglicht jedes Format, entweder national oder international.

Ich denke, der Hauptfaktor kann sein, wie genau Sie diese Zahlen abfragen und was Sie damit machen.

Don
quelle
Dies verfehlt den Punkt der Frage, nämlich den Standard der Inhalte der DB-Felder zu standardisieren, um eine eindeutige Übereinstimmung sicherzustellen. Wie stelle ich sicher, dass bei der Abfrage der Telefonnummer 800-555-1212 diese übereinstimmt, wenn der Benutzer "(800) 555-1212", "+1.800.555.1212" oder einen anderen entsprechenden Wert eingeben kann? Das ist die Herausforderung, die angegangen wird.
Irongaze.com
1

Ich finde, dass die meisten Webformulare die Landesvorwahl, die Vorwahl und dann die restlichen 7 Ziffern korrekt zulassen, aber fast immer vergessen, die Eingabe einer Nebenstelle zuzulassen. Dies führt fast immer dazu, dass ich wütende Worte ausspreche, da wir bei der Arbeit keine Empfangsdame haben und meine ext. # Benötigt wird, um mich zu erreichen.

Aaron
quelle
1

Ich finde, dass die meisten Webformulare die Landesvorwahl, die Vorwahl und dann die restlichen 7 Ziffern korrekt zulassen, aber fast immer vergessen, die Eingabe einer Nebenstelle zuzulassen. Dies führt fast immer dazu, dass ich wütende Worte ausspreche, da wir bei der Arbeit keine Empfangsdame haben und meine ext. # Benötigt wird, um mich zu erreichen.

Ich müsste das überprüfen, aber ich denke, unser DB-Schema ist ähnlich. Wir haben eine Landesvorwahl (möglicherweise standardmäßig in den USA, nicht sicher), eine Vorwahl, 7 Ziffern und eine Nebenstelle.

Thomas Owens
quelle
1

Was ist mit dem Speichern einer Freetext-Spalte, in der eine benutzerfreundliche Version der Telefonnummer angezeigt wird, und einer normalisierten Version, in der Leerzeichen, Klammern entfernt und '+' erweitert werden? Beispielsweise:

Benutzerfreundlich: +44 (0) 181 4642542

Normalisiert: 00441814642542

ColinYounger
quelle
10
Für wen genau ist +44 (0) 181 4642542 gedacht, um freundlich zu sein? Britische Benutzer, die möglicherweise nicht wissen, was sie mit der +44 tun sollen, wenn sie nicht daran gewöhnt sind, international zu wählen, oder internationale Benutzer, die nicht wissen, dass sie die (0) löschen sollen?
Mark Baker
0

Ich würde mich für ein Freetextfeld und ein Feld entscheiden, das eine rein numerische Version der Telefonnummer enthält. Ich würde die Darstellung der Telefonnummer dem Benutzer überlassen und das normalisierte Feld speziell für Telefonnummernvergleiche in TAPI-basierten Anwendungen oder beim Versuch verwenden, doppelte Einträge in einem Telefonverzeichnis zu finden. Natürlich schadet es nicht, dem Benutzer ein Eingabeschema zur Verfügung zu stellen, das Informationen wie separate Felder für Ländervorwahl (falls erforderlich), Vorwahl, Basisnummer und Nebenstelle hinzufügt.


quelle
0

Woher bekommen Sie die Telefonnummern? Wenn Sie sie von einem Teil des Telefonnetzes erhalten, erhalten Sie eine Ziffernfolge sowie einen Nummerntyp und -plan, z

441234567890 Typ / Plan 0x11 (was internationales E.164 bedeutet)

In den meisten Fällen ist es am besten, alle diese Werte so zu speichern, wie sie sind, und für die Anzeige zu normalisieren. Das Speichern normalisierter Zahlen kann jedoch hilfreich sein, wenn Sie sie als eindeutigen Schlüssel oder ähnliches verwenden möchten.

Mark Baker
quelle
0

Benutzerfreundlich: +44 (0) 181 464 2542 normalisiert: 00441814642542

Die (0) ist im internationalen Format nicht gültig. Siehe ITU-T E.123-Standard.

Das "normalisierte" Format wäre für US-Leser nicht nützlich, da sie 011 für den internationalen Zugriff verwenden.

Dave Sänger
quelle
0

Ich habe 3 verschiedene Methoden zum Speichern von Telefonnummern verwendet, abhängig von den Nutzungsanforderungen.

  1. Wenn die Nummer nur zum Abrufen durch Menschen gespeichert wird und nicht zum Durchsuchen verwendet wird, wird sie in einem Feld vom Typ Zeichenfolge genau so gespeichert, wie der Benutzer sie eingegeben hat.
  2. Wenn das Feld durchsucht werden soll, werden alle zusätzlichen Zeichen wie +, Leerzeichen und Klammern usw. entfernt und die verbleibende Nummer in einem Feld vom Typ Zeichenfolge gespeichert.
  3. Wenn die Telefonnummer von einem Computer / einer Telefonanwendung verwendet werden soll, muss sie in diesem Fall als gültige Telefonnummer eingegeben und gespeichert werden, die vom System verwendet werden kann. Diese Option ist natürlich am schwierigsten zu codieren zum.
Jimoc
quelle