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

时间:2008-09-03 15:22:34

标签: database

在数据库字段中存储电话号码的良好数据结构是什么?我正在寻找足够灵活的东西来处理国际号码,还有一些能够有效查询号码各个部分的东西。

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

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

非常低效。当它只是一个varchar字段时,寻找像区域代码之类的东西的查询变得非常棘手。

[编辑]

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

18 个答案:

答案 0 :(得分:75)

首先,除了国家代码之外,没有真正的标准。关于您所能做的最好的事情是通过国家代码识别特定电话号码所属的国家/地区,并根据该国家/地区的格式处理其余数字。

但是,通常情况下,电话设备等是标准化的,因此您几乎总能将给定的电话号码分解为以下组件

  • C国家代码1-10位数(现在4或更少,但可能会改变)
  • 区号(省/州/地区)代码0-10位(实际上可能分别需要区域字段和区域字段,而不是一个区号)
  • E Exchange(前缀或交换机)代码0-10位数
  • L行号1-10位数

使用此方法,您可以潜在地分隔数字,以便您可以找到可能彼此接近的人,因为他们具有相同的国家,地区和交换代码。随着手机不再是你可以指望的东西。

此外,每个国家内部都有不同的标准。您可以始终依赖美国的(AAA)EEE-LLLL,但在另一个国家/地区,您可能在城市(AAA)EE-LLL中进行交换,并且只能在农村地区(AAA)LLLL进行交换。您必须从某个窗体的顶部开始,并在您拥有信息时格式化它们。例如,国家/地区代码0的数字的其余部分具有已知格式,但对于国家/地区代码5432,您可能需要先检查区号,然后才能了解其余数字。

您可能还需要处理vanity这样的(800) Lucky-Guy号码,这需要认识到,如果是美国号码,则会有太多数字(并且您可能需要完整代表广告或其他目的)在美国,字母映射的数字与德国不同。

您可能还希望将整个号码分别存储为文本字段(具有国际化),以便您可以稍后返回并在更改时重新解析数字,或者作为备份以防有人提交错误方法来解析特定国家的格式并丢失信息。

答案 1 :(得分:57)

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

保留一个字符串,除非您对某些更高级的东西有特殊需求。

答案 2 :(得分:21)

Wikipedia page on E.164应该告诉你需要知道的一切。

答案 3 :(得分:8)

这是我提出的结构,我很感激反馈:

手机数据库字段应为varchar(42),格式如下:

CountryCode - Number x Extension

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

1-2125551234x1234

这将代表一个美国号码(国家代码1),区号/号码(212)555 1234和分机号码1234.

使用短划线分隔国家/地区代码可使国家/地区代码清楚地显示给正在浏览数据的人。这不是严格必要,因为国家/地区代码是“prefix codes”(您可以从左到右阅读它们,您将始终能够明确地确定国家/地区)。但是,由于国家代码的长度不同(目前在1到4个字符之间),除非使用某种分隔符,否则您无法轻易一目了然地看到国家/地区代码。

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

通过这种方式,您可以将整个数字(包括国家/地区代码和扩展名)存储在单个数据库字段中,然后您可以使用它来加速查询,而不是像您一样痛苦地加入用户定义的函数到目前为止。

为什么我选择varchar(42)?那么,首先,国际电话号码将有不同的长度,因此是“var”。我存储了一个短划线和一个“x”,所以这解释了“char”,无论如何,你不会对电话号码进行整数运算(我猜)所以尝试使用数字类型没有意义。至于42的长度,我根据Adam Davis的答案使用了所有字段的最大可能长度,并为短划线和'x'添加了2。

答案 4 :(得分:7)

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

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

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

答案 5 :(得分:6)

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

这样,数据库中的所有数据都是“干净”且没有格式化

答案 6 :(得分:3)

也许将电话号码部分存储在不同的列中,允许空白或空条目?

答案 7 :(得分:3)

好的,基于此页面上的信息,这是一个国际电话号码验证器的开始:

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

答案 8 :(得分:2)

存储

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

  • 长度没有限制
  • 扩展支持

要优化视图操作的性能,请将手机以RFC 3966字段旁边的“国家/国际”格式存储。

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

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

解析

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

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

请参阅official demo,以了解它有多大帮助。

答案 9 :(得分:2)

格式化数字的标准是https://jsfiddle.net/9ua5h7qc/1/,您应该始终以此格式存储数字。您不应该在与电话号码相同的字段中允许分机号码,这些号码应单独存储。至于数字与字母数字,这取决于你将如何处理这些数据。

答案 10 :(得分:1)

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

我想主要的驱动因素可能是您是如何查询这些数字以及您正在使用它们做些什么。

答案 11 :(得分:1)

  

我发现大多数网络表单正确地允许国家代码,区号,然后剩余的7位数但几乎总是忘记允许输入扩展名。这几乎总是让我愤怒的说话,因为在工作中我们没有接待员,我的分机#需要到达我。

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

答案 12 :(得分:1)

我发现大多数网络表单正确地允许国家代码,区号,然后剩余的7位数但几乎总是忘记允许输入扩展名。这几乎总是让我愤怒的说话,因为在工作中我们没有接待员,我的分机#需要到达我。

答案 13 :(得分:1)

如何存储显示电话号码的用户友好版本的自由文本列,然后是删除空格,括号和扩展“+”的标准化版本。例如:

用户友好: +44(0)181 4642542

标准化: 00441814642542

答案 14 :(得分:0)

我会去一个自由文本字段和一个包含电话号码纯数字版本的字段。我会将电话号码的表示留给用户,并使用规范化字段专门用于基于TAPI的应用程序中的电话号码比较,或者尝试在电话目录中查找双重条目。 当然,为用户提供一个入口方案可以增加智能,例如国家代码(如果需要),区号,基本号码和扩展名的单独字段。

答案 15 :(得分:0)

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

  1. 如果存储的号码仅供人工检索,并且不会用于搜索存储在字符串类型字段中的数字,与用户输入的完全相同。
  2. 如果要搜索该字段,则删除任何额外字符,例如+,空格和括号等,其余数字存储在字符串类型字段中。
  3. 最后,如果电话号码将被计算机/电话应用程序使用,那么在这种情况下,它需要输入并存储为系统可用的有效电话号码,当然这个选项是最难编码。

答案 16 :(得分:0)

你从哪里得到电话号码?如果您从电话网络的一部分获取它们,您将获得一串数字和数字类型和计划,例如

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

在大多数情况下,最好的办法是按原样存储所有这些内容,并对显示进行规范化,但如果要将标准化数字用作唯一键或类似数据,则存储规范化数字会很有用。

答案 17 :(得分:0)

  

方便用户:+44(0)181 464 2542规范化:00441814642542

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

“规范化”格式对美国读者没用,因为他们使用011进行国际访问。