在数据库字段中存储电话号码的良好数据结构是什么?我正在寻找足够灵活的东西来处理国际号码,还有一些能够有效查询号码各个部分的东西.
编辑:只是为了澄清这里的用例:我目前将数字存储在一个varchar字段中,并在客户输入时将其保留.然后,当代码需要该数字时,我将其标准化.问题是,如果我想查询几百万行来查找匹配的电话号码,它涉及一个功能,如
where dbo.f_normalizenum(num1) = dbo.f_normalizenum(num2)
Run Code Online (Sandbox Code Playgroud)
这是非常低效的.当只是一个varchar字段时,寻找像区域代码之类的东西的查询变得非常棘手.
[编辑]
人们在这里提出了很多好建议,谢谢!作为一个更新,这里是我现在正在做的事情:我仍然在varchar字段中存储与输入完全相同的数字,但是在查询时没有规范化事物,我有一个触发器,可以在插入记录时完成所有工作或更新.所以我对我需要查询的任何部分都有内联或重要内容,并且这些字段被编入索引以使查询运行得更快.
Ada*_*vis 76
首先,除了国家代码之外,没有真正的标准.关于您所能做的最好的事情是通过国家代码识别特定电话号码所属的国家/地区,并根据该国家/地区的格式处理其余数字.
但是,通常情况下,电话设备等是标准化的,因此您几乎总能将给定的电话号码分成以下组件
使用此方法,您可以潜在地分隔数字,以便您可以找到可能彼此接近的人,因为他们具有相同的国家,地区和交换代码.随着手机不再是你可以指望的东西.
此外,每个国家内部都有不同的标准.您可以始终依赖美国的(AAA)EEE-LLLL,但在另一个国家/地区,您可能在城市(AAA)EE-LLL中进行交换,并且只能在农村地区(AAA)LLLL中进行交换.您必须从某个窗体的顶部开始,并在您拥有信息时格式化它们.例如,国家/地区代码0的数字的其余部分具有已知格式,但对于国家/地区代码5432,您可能需要在了解其余数字之前检查区号.
您可能还想要处理vanity诸如此类的数字(800) Lucky-Guy,这需要认识到,如果它是美国数字,则有一个太多的数字(并且您可能需要完全代表广告或其他目的)并且在美国,字母映射到数字与德国不同.
您可能还希望将整个数字单独存储为文本字段(具有国际化),以便您可以稍后返回并在更改时重新解析数字,或者作为备份以防有人提交错误方法来解析特定国家/地区的格式并丢失信息.
Bjo*_*pen 55
亲吻 - 我厌倦了很多美国网站.他们有一些巧妙编写的代码来验证邮政编码和电话号码.当我输入我完全有效的挪威联系信息时,我发现它经常被拒绝.
保留一个字符串,除非你有一些特别需要更高级的东西.
这是我提出的结构,我很感激反馈:
电话数据库字段应为varchar(42),格式如下:
CountryCode - Number x Extension
因此,例如,在美国,我们可以:
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_GB或de_DE.
关于ITU-T E.164有很多信息,但它非常神秘.
我个人喜欢存储标准化的varchar电话号码(例如9991234567)的想法,当然,在显示时将该电话号码格式化为内联格式.
这样,数据库中的所有数据都是"干净"的,没有格式化
贮存
将电话存储在RFC 3966 中(如+1-202-555-0252, +1-202-555-7166;ext=22)。与E.164的主要区别是
为了优化获取数据的速度,除了 RFC 3966 字段之外,还要以国家/国际格式存储电话号码。
不要将国家/地区代码存储在单独的字段中,除非您有严重的理由。为什么?因为您不应该在 UI 上询问国家/地区代码。
大多数情况下,人们会在听到电话时进入电话。例如,如果本地格式以0或开头8,那么用户动态进行转换会很烦人(例如,“好吧,不要输入'0',选择国家并输入该人所说的其余内容在此字段中”)。
解析
谷歌支持您。他们的libphonenumber库可以验证和解析任何电话号码。几乎所有语言都有端口。
所以让用户只需输入“ 0449053501”或“ 04 4905 3501”或“ (04) 4905 3501”。该工具将为您解决其余的问题。
查看官方演示,感受一下它有多大帮助。