是否有用于在数据库中存储标准化电话号码的标准?

是否有用于在数据库中存储标准化电话号码的标准?

Is there a standard for storing normalized phone numbers in a database?

在数据库字段中存储电话号码的良好数据结构是什么?我正在寻找一种足够灵活的方式来处理国际号码,同时也希望能够有效查询号码的各个部分。

编辑:这里只是为了阐明用例:我目前将数字存储在单个varchar字段中,并且在客户输入时将其保留。然后,当代码需要数字时,我将其标准化。问题是,如果我想查询几百万行以查找匹配的电话号码,它涉及一个功能,例如

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

这是非常低效的。当查询仅是一个varchar字段时,寻找区号之类的查询也变得非常棘手。

[编辑]

人们在这里提出了很多好的建议,谢谢!作为更新,这是我现在正在做的事情:我仍然将输入的数字完全存储在varchar字段中,但是我没有在查询时对数据进行规范化,而是有一个触发器,可以在插入记录时完成所有工作或更新。因此,对于需要查询的任何部分,我都有int或bigints,并且对这些字段进行了索引以使查询运行更快。


首先,除了国家/地区代码之外,没有真正的标准。最好的办法就是通过国家/地区代码识别特定电话号码属于哪个国家/地区,然后根据该国家/地区的格式处理其余的号码。

通常,电话设备等是标准化的,因此您几乎总是可以将给定的电话号码分解为以下部分

  • 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,这要求您认识到,如果是美国数字,则数字太多(您可能需要完整地代表广告或其他目的),并且在美国,字母映射到数字的方式与在德国映射不同。

您可能还希望将整个数字分别存储为文本字段(具有国际化),以便稍后再返回并根据情况变化重新解析数字,或者作为备份,以防万一有人提出了错误的方法来解析特定国家/地区的格式并丢失信息。


吻-我已经厌倦了许多美国网站。他们有一些巧妙编写的代码来验证邮政编码和电话号码。当我输入完全有效的挪威联系信息时,我发现它经常被拒绝。

保留字符串,除非您对某些更高级的内容有特定的需求。


E.164上的Wikipedia页面应告诉您所有您需要了解的内容。


这是我建议的结构,感谢您的反馈:

电话数据库字段应为具有以下格式的varchar(42):

国家/地区代码-数字x扩展名

因此,例如,在美国,我们可以:

1-2125551234x1234

这将代表具有区号/号码(212)555 1234和扩展名1234的美国号码(国家代码1)。

用破折号分隔国家/地区代码可使正在阅读数据的人清楚国家/地区代码。这不是严格必需的,因为国家/地区代码是"前缀代码"(您可以从左到右阅读它们,并且始终可以明确确定国家/地区)。但是,由于国家/地区代码的长度是不同的(目前介于1到4个字符之间),除非您使用某种分隔符,否则您一眼就能分辨出国家/地区代码。

我使用" x"分隔扩展名,因为否则(在许多情况下)实际上是不可能确定哪个是数字,哪个是扩展名。

这样,您可以将完整的数字(包括国家代码和分机号)存储在单个数据库字段中,然后用于加快查询速度,而不必像到目前为止那样费心地加入用户定义的函数。

为什么选择varchar(42)?好吧,首先,国际电话号码的长度会有所不同,因此是" var"。我存储一个破折号和一个" x",以便解释" char",无论如何,您不会对电话号码进行整数运算(我想),因此尝试使用数字类型几乎没有任何意义。至于42的长度,我根据亚当·戴维斯(Adam Davis)的答案使用了所有字段的最大可能长度,并在破折号和'x'处加了2。


查找E.164。基本上,您将电话号码存储为国家/地区前缀和可选的pbx后缀的代码。那么显示就是本地化问题。验证也可以完成,但这也是一个本地化问题(基于国家/地区前缀)。

例如,+ 12125551212 + 202将在en_US语言环境中格式化为(212)555-1212 x202。 en_GBde_DE的格式将不同。

关于ITU-T E.164的信息很多,但它很神秘。


我个人比较喜欢存储规范化的varchar电话号码(例如9991234567),然后在显示时内联格式化该电话号码的想法。

这样,数据库中的所有数据都是"干净的"并且没有格式


好的,因此,根据此页面上的信息,以下是国际电话号码验证器的开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
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


也许将电话号码部分存储在不同的列中,以允许输入空白或空值?


存储

将电话存储在RFC 3966中(例如+1-202-555-0252+1-202-555-7166;ext=22)。与E.164的主要区别是

  • 长度无限制
  • 支持扩展

为了优化视图操作的性能,请以RFC 3966字段旁边的"国家/国际"格式存储电话。

除非您有充分的理由,否则请勿将国家/地区代码存储在单独的字段中。为什么?因为您不应该在用户界面上要求输入国家或地区代码。

人们通常会在听到电话时进入电话。例如。如果本地格式将从08开始,那么用户在头部进行数字转换就很烦人(例如"确定,请不要输入'0',请选择国家/地区并输入该人在此字段中所说的其余内容")。

解析

Google支持您,您可以使用其libphonenumber库来验证和解析任何电话号码。几乎所有语言都有端口。

因此,让用户只需输入" 0449053501"或" 04 4905 3501"或" (04) 4905 3501"。该工具将为您找出其余的信息。

观看官方演示,以了解它的帮助。


数字格式化的标准是e.164,您应始终以这种格式存储数字。您绝对不应将分机号与电话号码放在同一字段中,而应将其分开存储。至于数字还是字母数字,这取决于您将要处理的数据。


I find most web forms correctly allow for the country code, area code, then the remaining 7 digits but almost always forget to allow entry of an extension. This almost always ends up making me utter angry words, since at work we don't have a receptionist, and my ext.# is needed to reach me.

我必须检查一下,但是我认为我们的数据库架构是相似的。我们拥有国家代码(不确定,可能默认为美国),区号,7位数字和扩展名。


我发现大多数Web表单正确地允许输入国家代码,区号,然后是其余的7位数字,但几乎总是忘记允许输入扩展名。这几乎总是使我发脾气,因为在工作中我们没有接待员,需要我的分机号联系我。


如何存储一个自由文本列,该列显示电话号码的用户友好版本,然后存储一个标准化版本,该版本删除空格,方括号并扩展" +"。例如:

使用者友善:+44(0)181 4642542

标准化:00441814642542


我认为自由文本(也许是varchar(25))是使用最广泛的标准。这将允许使用任何格式,无论是国内格式还是国际格式。

我想主要的驱动因素可能是您查询这些数字的准确程度以及您对它们的处理方式。


根据使用要求,我使用了3种不同的方式来存储电话号码。

  • 如果该数字仅用于人类检索而存储,则不会完全按照用户输入的方式用于搜索存储在字符串类型字段中的数字。
  • 如果要搜索该字段,则将删除所有多余的字符,例如+,空格和方括号等,并将其余数字存储在字符串类型字段中。
  • 最后,如果电话号码将由计算机/电话应用程序使用,则在这种情况下,需要输入电话号码并将其存储为系统可用的有效电话号码,该选项当然是最难编码的对于。

  • 您从哪里得到电话号码?如果要从电话网络的一部分中获取它们,则会得到一串数字以及一个数字类型和计划,例如

    441234567890类型/计划0x11(表示国际E.164)

    在大多数情况下,最好的办法是按原样存储所有这些内容,并进行标准化以进行显示,尽管如果要将标准化编号用作唯一键或类似键,则存储标准化编号可能会很有用。


    User friendly: +44 (0)181 464 2542 normalised: 00441814642542

    (0)在国际格式中无效。参见ITU-T E.123标准。

    美国读者使用011进行国际访问时,"标准化"格式对他们没有用。


    我将使用自由文本字段和包含电话号码的纯数字版本的字段。我会将电话号码的表示形式留给用户,并使用标准化字段专门用于基于TAPI的应用程序中的电话号码比较,或在电话目录中查找重复条目时使用。
    当然,为用户提供一种添加智能的输入方案也无妨,例如国家代码(如有必要),区号,基本号码和分机号等单独字段。


    推荐阅读