Existe-t-il une norme pour stocker les numéros de téléphone normalisés dans une base de données?


95

Quelle est une bonne structure de données pour stocker les numéros de téléphone dans les champs de base de données? Je recherche quelque chose qui soit suffisamment flexible pour gérer les numéros internationaux, et aussi quelque chose qui permette d'interroger efficacement les différentes parties du numéro.

Edit: Juste pour clarifier le cas d'utilisation ici: je stocke actuellement les numéros dans un seul champ varchar, et je les laisse comme le client les a saisis. Ensuite, lorsque le numéro est nécessaire par code, je le normalise. Le problème est que si je veux interroger quelques millions de lignes pour trouver des numéros de téléphone correspondants, cela implique une fonction, comme

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

ce qui est terriblement inefficace. Les requêtes qui recherchent des éléments comme l'indicatif régional deviennent également extrêmement délicates lorsqu'il ne s'agit que d'un seul champ varchar.

[Éditer]

Les gens ont fait beaucoup de bonnes suggestions ici, merci! En guise de mise à jour, voici ce que je fais maintenant: je stocke toujours les numéros exactement tels qu'ils ont été saisis, dans un champ varchar, mais au lieu de normaliser les choses au moment de la requête, j'ai un déclencheur qui fait tout ce travail lorsque des enregistrements sont insérés ou mis à jour. J'ai donc des ints ou des bigints pour toutes les parties que j'ai besoin d'interroger, et ces champs sont indexés pour accélérer les requêtes.


Une réponse contemporaine à la question est ici - stackoverflow.com/a/51761170/968003 . L'essentiel - utilisez RFC 3966 pour le stockage et libphonenumber pour l'analyse / validation.
Alex Klaus

Réponses:


80

Premièrement, au-delà du code pays, il n'y a pas de véritable norme. Le mieux que vous puissiez faire est de reconnaître, par le code du pays, à quel pays appartient un numéro de téléphone particulier et de traiter le reste du numéro selon le format de ce pays.

En règle générale, cependant, l'équipement téléphonique et autres sont standardisés de sorte que vous pouvez presque toujours diviser un numéro de téléphone donné en composants suivants

  • C Indicatif pays 1-10 chiffres (actuellement 4 ou moins, mais cela peut changer)
  • Un indicatif régional (province / état / région) de 0 à 10 chiffres (peut en fait vouloir un champ régional et un champ régional séparément, plutôt qu'un indicatif régional)
  • E Code d'échange (préfixe ou commutateur) 0-10 chiffres
  • L Numéro de ligne 1-10 chiffres

Avec cette méthode, vous pouvez potentiellement séparer les numéros de sorte que vous puissiez trouver, par exemple, des personnes qui pourraient être proches les unes des autres parce qu'elles ont le même pays, la même région et les mêmes codes d'échange. Avec les téléphones portables, vous ne pouvez plus compter sur ce point.

De plus, à l'intérieur de chaque pays, il existe des normes différentes. Vous pouvez toujours compter sur un (AAA) EEE-LLLL aux États-Unis, mais dans un autre pays, vous pouvez avoir des échanges dans les villes (AAA) EE-LLL, et simplement des numéros de ligne dans les zones rurales (AAA) LLLL. Vous devrez commencer en haut dans un arbre d'une certaine forme et les formater comme vous avez des informations. Par exemple, l'indicatif de pays 0 a un format connu pour le reste du numéro, mais pour l'indicatif de pays 5432, vous devrez peut-être examiner l'indicatif régional avant de comprendre le reste du numéro.

Vous voudrez peut-être également traiter des vanitynombres tels que (800) Lucky-Guy, ce qui nécessite de reconnaître que, s'il s'agit d'un numéro américain, il y a un trop grand nombre de chiffres (et vous devrez peut-être une représentation complète à des fins publicitaires ou autres) et qu'aux États-Unis, les lettres correspondent au chiffres différemment qu'en Allemagne.

Vous pouvez également stocker le numéro entier séparément sous forme de champ de texte (avec internationalisation) afin de pouvoir revenir plus tard et réanalyser les numéros à mesure que les choses changent, ou comme sauvegarde au cas où quelqu'un soumettrait une mauvaise méthode pour analyser le format d'un pays particulier et perd des informations.


1
Connaissez-vous une bonne validation JavaScript pour essayer de valider cela?
cmcculloh

6
E164 fixe des limites beaucoup plus strictes sur la longueur des numéros: 1 à 3 pour les pays et une longueur maximale de 15. Cela ne changera pas de sitôt, compte tenu du système de téléphonie mondial.
Riche

Les longueurs que vous avez spécifiées semblent être, selon ITU-T E.164, complètement erronées. Il serait utile que vous puissiez publier un lien vers le document de normes à partir duquel vous tirez vos informations, ou expliquer pourquoi E.164 ne s'applique pas.
Abtin Forouzandeh

5
@Abtin - tous les systèmes téléphoniques ne sont pas conformes à l'UIT-T E.164. Cependant, la grande majorité d'entre eux le font et il vaut la peine de peser le choix entre être conforme aux normes et exclure certaines personnes ou aller au-delà de ce que dit la norme et accepter tout le monde. Notez que E.164 pourrait être considéré comme un sous-ensemble du schéma ci-dessus. Néanmoins, je pense que le meilleur format est celui que l'utilisateur a entré exactement, puis qu'un algorithme d'analyse le tokenise en cas de besoin, plutôt que de stocker le formulaire tokenisé dans la base de données.
Adam Davis

1) Peut-on supposer que tous les numéros internationaux sont conformes aux composants CAE? 2) Pouvez-vous supposer que le composant C est la seule chose qui diffère selon l'endroit d'où vous composez. Par exemple, le numéro américain 850-555-1234 a A = 850 et E = 555-1234, puis C = 1 si vous composez depuis les États-Unis et C = 001 si vous appelez depuis le Royaume-Uni. Le point étant quel que soit l'endroit d'où vous composez, A et E ne sont en aucun cas dynamiques, n'est-ce pas?
AaronLS

55

KISS - Je suis fatigué de nombreux sites Web américains. Ils ont un code intelligemment écrit pour valider les codes postaux et les numéros de téléphone. Lorsque je saisis mes coordonnées norvégiennes parfaitement valides, je trouve qu'elles sont souvent rejetées.

Laissez-le une chaîne, sauf si vous avez un besoin spécifique de quelque chose de plus avancé.


Un bon vieux nvarchar(42)avec un peu de validation /^+?[0-9 -\.\(\)#*]{4,41}$/fonctionne très bien!
SandRock

Je suis d'accord, mais pas d'accord en même temps. En règle générale, vous voulez faire quelque chose avec ce numéro de téléphone stocké, comme l'afficher. Plutôt que d'essayer de l'analyser suffisamment pour l'afficher comme vous le souhaitez, je préfère le stocker de manière normalisée. Maintenant, je ne dis pas que nous devrions aller aussi loin pour appliquer des parenthèses autour de l'indicatif régional. Ce que je dis, c'est que ce sont tous des nombres, pas de tirets, etc.
The Muffin Man

4
Je pense que les numéros de téléphone doivent être analysés avant de les stocker, afin qu'ils puissent être validés et stockés de manière normalisée. L'analyse et le formatage internationaux des numéros de téléphone sont parfaitement possibles avec le numéro googlei18n / libphonenumber .
Roel

21

La page Wikipedia sur E.164 devrait vous dire tout ce que vous devez savoir.


3
non, cette norme définit simplement comment les numéros de téléphone sont structurés (ils sont constitués de trois numéros), mais elle ne spécifie pas comment ils doivent être affichés et / ou stockés. Ai-je dit standard? Je voulais dire recommandation .
BlueWizard

8

Voici ma structure proposée, j'apprécierais vos commentaires:

Le champ de la base de données de téléphone doit être un varchar (42) au format suivant:

CountryCode - Numéro x Extension

Ainsi, par exemple, aux États-Unis, nous pourrions avoir:

1-2125551234x1234

Cela représenterait un numéro américain (indicatif de pays 1) avec l'indicatif régional / numéro (212) 555 1234 et l'extension 1234.

Séparer le code du pays par un tiret rend le code de pays clair pour quelqu'un qui consulte les données. Ce n'est pas strictement nécessaire car les codes de pays sont des " codes préfixes " (vous pouvez les lire de gauche à droite et vous pourrez toujours déterminer sans ambiguïté le pays). Mais, comme les codes de pays ont des longueurs variables (entre 1 et 4 caractères pour le moment), vous ne pouvez pas facilement dire d'un coup d'œil le code de pays à moins d'utiliser une sorte de séparateur.

J'utilise un "x" pour séparer l'extension car sinon, il ne serait pas vraiment possible (dans de nombreux cas) de déterminer quel était le numéro et quelle était l'extension.

De cette façon, vous pouvez stocker le numéro entier, y compris le code du pays et l'extension, dans un seul champ de base de données, que vous pouvez ensuite utiliser pour accélérer vos requêtes, au lieu de vous joindre à une fonction définie par l'utilisateur comme vous l'avez fait péniblement jusqu'à présent. .

Pourquoi ai-je choisi un varchar (42)? Eh bien, tout d'abord, les numéros de téléphone internationaux seront de longueurs variées, d'où le "var". Je stocke un tiret et un "x", ce qui explique le "char", et de toute façon, vous ne ferez pas d'arithmétique entière sur les numéros de téléphone (je suppose) donc cela n'a pas de sens d'essayer d'utiliser un type numérique . Quant à la longueur de 42, j'ai utilisé la longueur maximale possible de tous les champs additionnés, sur la base de la réponse d'Adam Davis, et j'ai ajouté 2 pour le tiret et le «x».


7

Recherchez E.164. Fondamentalement, vous stockez le numéro de téléphone sous forme de code commençant par le préfixe du pays et un suffixe pbx facultatif. L'affichage est alors un problème de localisation. La validation peut également être effectuée, mais c'est aussi un problème de localisation (basé sur le préfixe du pays).

Par exemple, + 12125551212 + 202 serait formaté dans les paramètres régionaux en_US comme (212) 555-1212 x202. Il aurait un format différent dans en_GBou de_DE.

Il y a pas mal d'informations sur ITU-T E.164, mais c'est assez cryptique.


6

J'aime personnellement l'idée de stocker un numéro de téléphone varchar normalisé (par exemple 9991234567) puis, bien sûr, de formater ce numéro de téléphone en ligne lorsque vous l'affichez.

De cette façon, toutes les données de votre base de données sont «propres» et sans formatage


4

Espace de rangement

Stockez les téléphones dans la RFC 3966 (comme +1-202-555-0252, +1-202-555-7166;ext=22). La principale différence avec E.164 est

  • Pas de limite de longueur
  • Prise en charge des extensions

Pour optimiser les performances des opérations d'affichage, stockez le téléphone au format National / International à côté du champ RFC 3966.

Ne stockez pas le code du pays dans un champ séparé, sauf si vous avez une raison sérieuse à cela. Pourquoi? Parce que vous ne devriez pas demander le code du pays sur l'interface utilisateur.

La plupart du temps, les gens entrent dans les téléphones lorsqu'ils les entendent. Par exemple, si le format local commence à partir de 0ou 8, il serait ennuyeux pour l'utilisateur d'effectuer la transformation numérique dans l'en-tête (comme, " OK, ne tapez pas '0', choisissez le pays et tapez le reste de ce que le personne a dit dans ce domaine ").

Analyse

Google vous soutient et vous pouvez valider et analyser n'importe quel numéro de téléphone en utilisant leur bibliothèque libphonenumber . Il existe des ports vers presque toutes les langues.

Alors laissez l'utilisateur entrer simplement " 0449053501" ou "04 4905 3501 " ou " (04) 4905 3501". L'outil déterminera le reste pour vous.

Voir la démo officielle , pour avoir une idée de ce que cela aide.


3

Peut-être stocker les sections de numéro de téléphone dans différentes colonnes, permettant des entrées vides ou nulles?


3

Ok, donc basé sur les informations sur cette page, voici un début sur un validateur de numéro de téléphone international:

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

Librement basé sur un script de cette page: http://www.webcheatsheet.com/javascript/form_validation.php


2

La norme pour le formatage des nombres est e.164 , vous devez toujours stocker les nombres dans ce format. Vous ne devez jamais autoriser le numéro de poste dans le même champ que le numéro de téléphone, ceux-ci doivent être stockés séparément. En ce qui concerne le numérique vs alphanumérique, cela dépend de ce que vous allez faire avec ces données.


1

Je pense que le texte libre (peut-être varchar (25)) est la norme la plus utilisée. Cela permettra n'importe quel format, national ou international.

Je suppose que le principal facteur déterminant peut être la façon dont vous interrogez exactement ces chiffres et ce que vous en faites.


Cela manque le point de la question, qui est de normaliser le contenu des champs DB pour assurer une correspondance unique. Comment puis-je m'assurer que lorsque j'interroge le numéro de téléphone 800-555-1212 qu'il correspond si l'utilisateur peut entrer "(800) 555-1212", "+1.800.555.1212" ou toute autre valeur équivalente? C'est le défi à relever.
Irongaze.com

1

Je trouve que la plupart des formulaires Web autorisent correctement l'indicatif du pays, l'indicatif régional, puis les 7 chiffres restants, mais oublient presque toujours d'autoriser l'entrée d'une extension. Cela finit presque toujours par me faire prononcer des mots de colère, car au travail, nous n'avons pas de réceptionniste et mon # ext. Est nécessaire pour me joindre.


1

Je trouve que la plupart des formulaires Web autorisent correctement l'indicatif du pays, l'indicatif régional, puis les 7 chiffres restants, mais oublient presque toujours d'autoriser l'entrée d'une extension. Cela finit presque toujours par me faire prononcer des mots de colère, car au travail, nous n'avons pas de réceptionniste et mon # ext. Est nécessaire pour me joindre.

Je devrais vérifier, mais je pense que notre schéma DB est similaire. Nous détenons un code de pays (il peut s'agir par défaut des États-Unis, pas sûr), un indicatif régional, 7 chiffres et une extension.


1

Qu'en est-il de stocker une colonne de texte libre qui montre une version conviviale du numéro de téléphone, puis une version normalisée qui supprime les espaces, les crochets et développe '+'. Par exemple:

Convivialité: +44 (0) 181 4642542

Normalisé: 00441814642542


10
Pour qui exactement le +44 (0) 181 4642542 est-il censé être convivial? Les utilisateurs britanniques qui ne savent peut-être pas quoi faire avec le +44 s'ils ne sont pas habitués à appeler à l'international, ou les utilisateurs internationaux qui ne savent pas qu'ils sont censés abandonner le (0)?
Mark Baker

0

J'opterais pour un champ de texte libre et un champ qui contient une version purement numérique du numéro de téléphone. Je laisserais la représentation du numéro de téléphone à l'utilisateur et utiliserais le champ normalisé spécifiquement pour les comparaisons de numéros de téléphone dans les applications basées sur TAPI ou lorsque j'essayais de trouver des entrées doubles dans un annuaire téléphonique. Bien sûr, cela ne fait pas de mal de fournir à l'utilisateur un schéma de saisie qui ajoute des informations telles que des champs séparés pour le code de pays (si nécessaire), l'indicatif régional, le numéro de base et l'extension.


0

D'où obtenez-vous les numéros de téléphone? Si vous les obtenez à partir d'une partie du réseau téléphonique, vous obtiendrez une chaîne de chiffres et un type de numéro et un plan, par exemple

441234567890 type / plan 0x11 (ce qui signifie international E.164)

Dans la plupart des cas, la meilleure chose à faire est de stocker tous ces éléments tels quels et de les normaliser pour l'affichage, bien que stocker des nombres normalisés puisse être utile si vous souhaitez les utiliser comme clé unique ou similaire.


0

Convivialité: +44 (0) 181464 2542 normalisé: 00441814642542

Le (0) n'est pas valide au format international. Voir la norme ITU-T E.123.

Le format «normalisé» ne serait pas utile aux lecteurs américains car ils utilisent 011 pour l'accès international.


0

J'ai utilisé 3 façons différentes de stocker des numéros de téléphone en fonction des exigences d'utilisation.

  1. Si le numéro est stocké uniquement pour la récupération humaine et ne sera pas utilisé pour rechercher, il est stocké dans un champ de type chaîne exactement comme l'utilisateur l'a entré.
  2. Si le champ doit être recherché, tous les caractères supplémentaires, tels que +, espaces et crochets, etc. sont supprimés et le nombre restant est stocké dans un champ de type chaîne.
  3. Enfin, si le numéro de téléphone doit être utilisé par une application informatique / téléphonique, dans ce cas, il devra être saisi et stocké en tant que numéro de téléphone valide utilisable par le système, cette option étant bien sûr la plus difficile à coder pour.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.