¿Existe un estándar para almacenar números de teléfono normalizados en una base de datos?


95

¿Cuál es una buena estructura de datos para almacenar números de teléfono en los campos de la base de datos? Estoy buscando algo que sea lo suficientemente flexible para manejar números internacionales, y también algo que permita consultar las distintas partes del número de manera eficiente.

Editar: Solo para aclarar el caso de uso aquí: actualmente almaceno números en un solo campo varchar, y los dejo tal como los ingresó el cliente. Luego, cuando el código necesita el número, lo normalizo. El problema es que si quiero consultar unos pocos millones de filas para encontrar números de teléfono coincidentes, implica una función, como

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

que es terriblemente ineficaz. Además, las consultas que buscan cosas como el código de área se vuelven extremadamente complicadas cuando se trata de un solo campo varchar.

[Editar]

La gente ha hecho muchas buenas sugerencias aquí, ¡gracias! Como actualización, esto es lo que estoy haciendo ahora: todavía almaceno números exactamente como se ingresaron, en un campo varchar, pero en lugar de normalizar las cosas en el momento de la consulta, tengo un disparador que hace todo ese trabajo cuando se insertan los registros o actualizado. Así que tengo ints o bigints para las partes que necesito consultar, y esos campos están indexados para que las consultas se ejecuten más rápido.


Una respuesta contemporánea a la pregunta está aquí: stackoverflow.com/a/51761170/968003 . La esencia de la misma: use RFC 3966 para almacenamiento y número de teléfono para análisis / validación.
Alex Klaus

Respuestas:


80

Primero, más allá del código de país, no existe un estándar real. Lo mejor que puede hacer es reconocer, por el código de país, a qué país pertenece un número de teléfono en particular y tratar el resto del número de acuerdo con el formato de ese país.

Sin embargo, en general, el equipo telefónico y demás están estandarizados, por lo que casi siempre puede dividir un número de teléfono determinado en los siguientes componentes

  • C Código de país de 1 a 10 dígitos (en este momento 4 o menos, pero eso puede cambiar)
  • Un código de área (provincia / estado / región) código de 0 a 10 dígitos (en realidad, es posible que desee un campo de región y un campo de área por separado, en lugar de un código de área)
  • E Código de intercambio (prefijo o conmutador) 0-10 dígitos
  • L Número de línea 1-10 dígitos

Con este método, puede separar números de manera que pueda encontrar, por ejemplo, personas que podrían estar cerca unas de otras porque tienen el mismo país, área y códigos de intercambio. Sin embargo, con los teléfonos móviles eso ya no es algo con lo que pueda contar.

Además, dentro de cada país existen diferentes estándares. Siempre puede depender de un EEE-LLLL (AAA) en los EE. UU., Pero en otro país puede tener intercambios en las ciudades (AAA) EE-LLL, y simplemente números de línea en las áreas rurales (AAA) LLLL. Tendrá que comenzar en la parte superior de un árbol de alguna forma y formatearlos según tenga la información. Por ejemplo, el código de país 0 tiene un formato conocido para el resto del número, pero para el código de país 5432, es posible que deba examinar el código de área antes de comprender el resto del número.

Es posible que también desee manejar vanitynúmeros como(800) Lucky-Guy , lo que requiere reconocer que, si es un número de EE. UU., Hay demasiados dígitos (y es posible que necesite una representación completa para publicidad u otros fines) y que en los EE. UU. Las letras se asignan al números de manera diferente que en Alemania.

También es posible que desee almacenar el número completo por separado como un campo de texto (con internacionalización) para que pueda volver más tarde y volver a analizar los números a medida que cambian las cosas, o como copia de seguridad en caso de que alguien envíe un método incorrecto para analizar el formato de un país en particular. y pierde información.


1
¿Conoce alguna buena validación de JavaScript para intentar validar esto?
cmcculloh

6
E164 establece límites mucho más estrictos en la longitud de los números: 1-3 para países, y una longitud máxima de 15. Esto no cambiará pronto, conociendo el sistema de telefonía global.
Rich

Las longitudes que ha especificado parecen ser, según ITU-T E.164, completamente incorrectas. Sería útil si pudiera publicar un enlace al documento de estándares del que deriva su información, o explicar por qué E.164 no se aplica.
Abtin Forouzandeh

5
@Abtin: no todos los sistemas telefónicos cumplen con ITU-T E.164. Sin embargo, la gran mayoría de ellos lo hace, y vale la pena sopesar la elección entre cumplir con los estándares y bloquear a algunas personas o ir más allá de lo que dice el estándar y aceptar a todos. Tenga en cuenta que E.164 podría verse como un subconjunto del esquema anterior. Aún así, creo que el mejor formato es lo que el usuario ingresó exactamente, y luego hacer que un algoritmo de análisis lo tokenice cuando sea necesario, en lugar de almacenar el formulario tokenizado en la base de datos.
Adam Davis

1) ¿Se puede asumir que todos los números internacionales se ajustan a tener los componentes CAE? 2) ¿Puede suponer que el componente C es lo único que es diferente dependiendo de dónde esté marcando? Por ejemplo, el número de EE. UU. 850-555-1234 tiene A = 850 y E = 555-1234, y luego C = 1 si marca desde EE. UU. Y C = 001 si marca desde Reino Unido. El punto es independientemente de dónde esté marcando, A y E no son dinámicos de ninguna manera, ¿correcto?
AaronLS

55

KISS - Me estoy cansando de muchos de los sitios web de EE. UU. Tienen un código inteligentemente escrito para validar códigos postales y números de teléfono. Cuando escribo mi información de contacto noruego perfectamente válida, encuentro que a menudo es rechazada.

Déjelo una cadena, a menos que tenga alguna necesidad específica de algo más avanzado.


¡Un buen viejo nvarchar(42)con un poco de validación /^+?[0-9 -\.\(\)#*]{4,41}$/funciona muy bien!
SandRock

Estoy de acuerdo, pero en desacuerdo al mismo tiempo. Por lo general, desea hacer algo con ese número de teléfono almacenado, como mostrarlo. En lugar de seguir este camino de tratar de analizarlo lo suficiente para mostrarlo como desee, prefiero almacenarlo de forma normalizada. No estoy diciendo que debamos ir tan lejos como para hacer cumplir los paréntesis alrededor del código de área. Lo que digo es que es todos los números sin guiones, etc.
al hombre de mollete

4
Creo que los números de teléfono deben analizarse antes de almacenarlos, para que puedan validarse y almacenarse de forma normalizada. El análisis y el formateo internacional de números de teléfono es perfectamente posible con el número googlei18n / libphonenumber .
Roel

21

La página de Wikipedia sobre E.164 debería decirle todo lo que necesita saber.


3
no, ese estándar solo define cómo se estructuran los números de teléfono (están hechos de tres números) pero no especifica cómo se mostrarán y / o almacenarán. ¿Dije estándar? Me refiero a recomendación .
BlueWizard

8

Aquí está mi estructura propuesta, agradecería sus comentarios:

El campo de la base de datos del teléfono debe ser un varchar (42) con el siguiente formato:

CountryCode - Número x Extensión

Entonces, por ejemplo, en EE. UU., Podríamos tener:

1-2125551234x1234

Esto representaría un número de EE. UU. (Código de país 1) con código de área / número (212) 555 1234 y extensión 1234.

Separar el código del país con un guión hace que el código del país sea claro para alguien que está examinando los datos. Esto no es estrictamente necesario porque los códigos de país son " códigos de prefijo " (puede leerlos de izquierda a derecha y siempre podrá determinar sin ambigüedades el país). Pero, dado que los códigos de país tienen diferentes longitudes (entre 1 y 4 caracteres en este momento), no puede saber fácilmente de un vistazo el código de país a menos que use algún tipo de separador.

Utilizo una "x" para separar la extensión porque de otro modo no sería posible (en muchos casos) averiguar cuál era el número y cuál era la extensión.

De esta manera, puede almacenar el número completo, incluido el código de país y la extensión, en un solo campo de base de datos, que luego puede usar para acelerar sus consultas, en lugar de unirse a una función definida por el usuario como lo ha estado haciendo hasta ahora. .

¿Por qué elegí un varchar (42)? Bueno, en primer lugar, los números de teléfono internacionales serán de distintas longitudes, de ahí la "var". Estoy almacenando un guión y una "x", de modo que eso explica el "char" y, de todos modos, no harás aritmética de enteros en los números de teléfono (supongo), por lo que no tiene mucho sentido intentar usar un tipo numérico . En cuanto a la longitud de 42, utilicé la longitud máxima posible de todos los campos sumados, según la respuesta de Adam Davis, y agregué 2 para el guión y la "x".


7

Busque E.164. Básicamente, almacena el número de teléfono como un código que comienza con el prefijo del país y un sufijo pbx opcional. La visualización es entonces un problema de localización. También se puede realizar la validación, pero también es un problema de localización (según el prefijo del país).

Por ejemplo, + 12125551212 + 202 se formateará en la configuración regional en_US como (212) 555-1212 x202. Tendría un formato diferente en en_GBo de_DE.

Hay bastante información sobre ITU-T E.164, pero es bastante críptica.


6

Personalmente, me gusta la idea de almacenar un número de teléfono varchar normalizado (por ejemplo, 9991234567) y luego, por supuesto, formatear ese número de teléfono en línea a medida que lo muestra.

De esta forma, todos los datos de su base de datos están "limpios" y sin formato.


4

Almacenamiento

Almacene los teléfonos en RFC 3966 (como +1-202-555-0252, +1-202-555-7166;ext=22). La principal diferencia con E.164 son

  • Sin límite de longitud
  • Soporte de extensiones

Para optimizar el rendimiento de las operaciones de visualización, almacene el teléfono en formato nacional / internacional junto al campo RFC 3966.

No guarde el código de país en un campo separado a menos que tenga una razón seria para ello. ¿Por qué? Porque no debe solicitar el código de país en la interfaz de usuario.

En su mayoría, las personas ingresan a los teléfonos cuando los escuchan. Por ejemplo, si el formato local comenzará desde 0o 8, sería molesto para el usuario hacer la transformación numérica en la cabeza (como, " OK, no escriba '0', elija el país y escriba el resto de lo que persona dijo en este campo ").

Analizando

Google te respalda y puedes validar y analizar cualquier número de teléfono usando su biblioteca libphonenumber . Hay puertos para casi cualquier idioma.

Así que deje que el usuario ingrese " 0449053501" o " 04 4905 3501" o " (04) 4905 3501". La herramienta se encargará del resto por ti.

Vea la demostración oficial para tener una idea de cuánto ayuda.


3

¿Quizás almacenar las secciones de números de teléfono en diferentes columnas, permitiendo entradas en blanco o nulas?


3

De acuerdo, según la información de esta página, aquí hay un comienzo en un validador de número de teléfono internacional:

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

Basado libremente en un script de esta página: http://www.webcheatsheet.com/javascript/form_validation.php


2

El estándar para formatear números es e.164 . Siempre debe almacenar números en este formato. Nunca debe permitir el número de extensión en el mismo campo con el número de teléfono, estos deben almacenarse por separado. En cuanto a numérico vs alfanumérico, depende de lo que vaya a hacer con esos datos.


1

Creo que el texto libre (quizás varchar (25)) es el estándar más utilizado. Esto permitirá cualquier formato, ya sea nacional o internacional.

Supongo que el principal factor determinante puede ser la forma exacta en que consulta estos números y lo que hace con ellos.


Esto pierde el sentido de la pregunta, que es estandarizar el contenido de los campos de la base de datos para garantizar una coincidencia única. ¿Cómo me aseguro de que cuando solicito el número de teléfono 800-555-1212 coincida con si el usuario puede ingresar "(800) 555-1212", "+1.800.555.1212" o cualquier otro valor equivalente? Ese es el desafío que se está abordando.
Irongaze.com

1

Encuentro que la mayoría de los formularios web permiten correctamente el código de país, el código de área y luego los 7 dígitos restantes, pero casi siempre olvido permitir la entrada de una extensión. Esto casi siempre termina haciendo que pronuncie palabras de enojo, ya que en el trabajo no tenemos recepcionista y se necesita mi número de extensión para comunicarse conmigo.


1

Encuentro que la mayoría de los formularios web permiten correctamente el código de país, el código de área y luego los 7 dígitos restantes, pero casi siempre olvido permitir la entrada de una extensión. Esto casi siempre termina haciendo que pronuncie palabras de enojo, ya que en el trabajo no tenemos recepcionista y se necesita mi número de extensión para comunicarse conmigo.

Tendría que comprobarlo, pero creo que nuestro esquema de base de datos es similar. Tenemos un código de país (puede ser el predeterminado de EE. UU., No estoy seguro), un código de área, 7 dígitos y una extensión.


1

¿Qué hay de almacenar una columna de texto libre que muestra una versión fácil de usar del número de teléfono, luego una versión normalizada que elimina espacios, corchetes y expande '+'? Por ejemplo:

Fácil de usar: +44 (0) 181 4642542

Normalizado: 00441814642542


10
¿Para quién es exactamente +44 (0) 181 4642542 destinado a ser amigable? ¿Usuarios del Reino Unido que quizás no sepan qué hacer con el +44 si no están acostumbrados a marcar internacionalmente, o usuarios internacionales que no sabrán que se supone que deben eliminar el (0)?
Mark Baker

0

Yo optaría por un campo de texto libre y un campo que contenga una versión puramente numérica del número de teléfono. Dejaría la representación del número de teléfono al usuario y usaría el campo normalizado específicamente para las comparaciones de números de teléfono en aplicaciones basadas en TAPI o cuando intento encontrar entradas dobles en un directorio telefónico. Por supuesto, no está de más proporcionar al usuario un esquema de entrada que agregue inteligencia como campos separados para el código de país (si es necesario), código de área, número base y extensión.


0

¿De dónde sacas los números de teléfono? Si los obtiene de parte de la red telefónica, obtendrá una cadena de dígitos y un tipo de número y plan, p. Ej.

441234567890 tipo / plan 0x11 (que significa E.164 internacional)

En la mayoría de los casos, lo mejor que puede hacer es almacenar todos estos como están y normalizarlos para su visualización, aunque almacenar números normalizados puede resultar útil si desea utilizarlos como una clave única o similar.


0

Fácil de usar: +44 (0) 181464 2542 normalizado: 00441814642542

El (0) no es válido en el formato internacional. Consulte el estándar ITU-T E.123.

El formato "normalizado" no sería útil para los lectores estadounidenses, ya que utilizan 011 para acceso internacional.


0

He utilizado 3 formas diferentes de almacenar números de teléfono según los requisitos de uso.

  1. Si el número se almacena solo para recuperación humana y no se usará para buscar, está almacenado en un campo de tipo cadena exactamente como lo ingresó el usuario.
  2. Si se va a buscar en el campo, entonces se eliminan los caracteres adicionales, como +, espacios y corchetes, etc., y el número restante se almacena en un campo de tipo cadena.
  3. Finalmente, si el número de teléfono va a ser utilizado por una aplicación de computadora / teléfono, entonces en este caso deberá ser ingresado y almacenado como un número de teléfono válido que pueda usar el sistema, siendo esta opción, por supuesto, la más difícil de codificar. para.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.