在数据库中存储邮政地址的最佳实践(RDBMS) ?

对于在 RDBMS 中存储邮政地址的最佳实践有什么好的参考吗?似乎有很多权衡可以做出,有很多利弊需要评估——这肯定已经被一次又一次地做过了吧?也许有人至少写了一些经验教训的地方?

我所说的折衷的例子是将邮政编码存储为一个整数字段 vs 一个字符字段,房子号码应该存储为一个单独的字段还是地址行1的一部分,套房/公寓/等号码应该标准化还是仅仅存储为地址行2中的一段文本,你如何处理 zip + 4(单独的字段或一个大字段,整数 vs 文本) ?等等。

我现在主要关心的是美国的地址,但是我想这里有一些最好的实践来帮助你为全球化做好准备(例如,适当的命名字段,比如地区,而不是州或者邮政编码,而不是邮政编码,等等)。

102978 次浏览

您当然应该参考“ 这是在关系数据库中建立地址信息模型的好方法吗”,但您的问题不是直接重复的。

肯定有很多预先存在的答案(例如,请查看 数据库答案上的示例数据模型)。许多预先存在的答案在某些情况下是有缺陷的(根本没有选择数据库答案)。

需要考虑的一个主要问题是地址的范围。如果您的数据库必须处理国际地址,那么您必须比只处理一个国家的地址更加灵活。

在我看来,经常(并不意味着 一直都是)明智的做法是既记录地址的“地址标签图像”,又单独分析内容。这允许您处理邮政编码放置之间的差异,例如,不同国家之间的差异。当然,您可以编写一个分析器和一个格式化程序来处理不同国家的异常情况(例如,美国地址有2或3行; 相比之下,英国地址可能有更多; 我定期写的一个地址有9行)。但是让人工进行分析和格式化并让数据库管理系统只存储数据会更容易。

你肯定应该考虑把房号存储为一个字符字段,而不是一个数字,因为有一些特殊情况,比如“半数”,或者我现在的地址,类似于“129A”——但是 A 不被认为是送货服务的公寓号码。

以数字或 VARCHAR 形式存储 ZIP 的“权衡”在哪里?这只是一种选择——这不是一种权衡,除非两者都有好处,你必须放弃一些好处才能得到其他好处。

除非拉链的总和有任何意义,否则拉链作为数字是没有用的。

除非你打算对街道号码或邮政编码进行数学计算,否则你只是把它们存储为数字而招致未来的痛苦。

您可能会在这里或那里节省几个字节,并且可能获得更快的索引,但是当国家邮政部门或您正在处理的其他国家决定将 alpha 引入代码时,您会怎么做?

磁盘空间的成本将会比以后修复它的成本要便宜得多... 2000年以后有人会这样做吗?

加上@乔纳森 · 莱弗勒和@Paul Fisher所说的

如果您曾经预期有加拿大或墨西哥的邮政地址添加到您的要求,存储 postal-code作为一个字符串是必须的。加拿大有字母数字的邮政编码,我一下子想不起来墨西哥是什么样子了。

作为一个“国际”用户,没有什么比处理一个只面向美国格式地址的网站更令人沮丧的了。一开始有点粗鲁,但当验证过于热心时,就会成为一个严重的问题。

如果你想走向全球,我唯一的建议就是让事情自由发展。不同的国家有不同的惯例——在一些国家,门牌号码在街道名称之前,在一些国家,门牌号码在街道名称之后。有些州,有些地区,有些县,有些组合。在英国,邮政编码不是邮政编码,而是包含字母和数字的邮政编码。

我只建议使用大约10行的可变长度字符串,以及一个单独的邮政编码字段(并且要注意如何描述它以应对国家敏感性)。让用户/客户决定如何写他们的地址。

我已经这样做了(严格地模拟数据库中的地址结构) ,我再也不会这样做了。你无法想象这些例外是多么的疯狂,你必须把它们作为一个规则来考虑。

我依稀记得挪威邮政编码的一些问题(我认为) ,除了奥斯陆有18个左右的位置之外,挪威邮政编码全部是4个位置。

我敢肯定,从我们开始使用地理上正确的邮政编码的那一刻起,我们自己的国家地址,相当多的人开始抱怨他们的邮件到达太晚。结果发现这些人居住在邮政区域之间的边界附近,尽管有人真的住在邮政区域,比如说1600年,但实际上他的邮件应该寄到1610邮政区域,因为实际上是邻近的邮政区域在为他服务,所以把他的邮件寄到正确的邮政区域要多花几天时间才能到达,因为正确的邮政局需要不必要的干预,才能把邮件转发到不正确的邮政区域..。

(我们最终将这些人的国外地址注册为 ISO 代码‘ ZZ’。)

这可能有点夸张,但是如果您需要一个可以在多个国家使用的解决方案,并且您需要以编程方式处理地址的某些部分:

您可以使用两个表来处理国家特定的地址: 一个通用表有10个 VARCHAR2列,10个 Number 列,另一个表将这些字段映射到提示,并且有一个国家列将地址结构绑定到一个国家。

如果你需要关于其他国家如何使用邮政地址的全面信息,这里有一个很好的参考链接(哥伦比亚大学) :

弗兰克强制性邮政地址指南
国际邮件的有效处理

我只是将所有字段放在一个大的 NVARCHAR (1000)字段中,并为用户提供一个 textarea 元素来输入值(除非您想对邮政编码执行分析)。所有这些地址行1,地址行2等输入只是如此恼人,如果你有一个地址不适合这种格式(你知道,还有其他国家比美国)。

我发现从最小的离散单元到最大的单元列出所有可能的字段是最简单的方法。用户将填写他们认为合适的字段。我的地址表是这样的:

*********************************
Field              Type
*********************************
address_id (PK)    int
unit               string
building           string
street             string
city               string
region             string
country            string
address_code       string
*********************************

如果你曾经需要验证一个地址或者使用它来处理信用卡付款,你至少需要一个小的结构。自由格式的文本块不能很好地解决这个问题。

邮政编码是一个常见的可选字段,用于验证支付卡交易而不使用整个地址。因此,需要一个单独的、大小适中的字段(至少10个字符)。

灵感来自 数据库答案

Line1
Line2
Line3
City
Country_Province
PostalCode
CountryId
OtherDetails

对于更多的国际用途,需要考虑的一种模式是 Drupal 地址字段使用的模式。它基于 XNAL 标准,似乎涵盖了大多数国际案件。对这个模块稍作深入研究,就会发现一些在国际上用于解释和验证地址的好东西。它还有一套很好的行政区(省,州,州等)与 ISO 代码。

下面是从模块页面复制的模式要点:

country => Country (always required, 2 character ISO code)
name_line => Full name (default name entry)
first_name => First name
last_name => Last name
organisation_name => Company
administrative_area => State / Province / Region (ISO code when available)
sub_administrative_area => County / District (unused)
locality => City / Town
dependent_locality => Dependent locality (unused)
postal_code => Postal code / ZIP Code
thoroughfare => Street address
premise => Apartment, Suite, Box number, etc.
sub_premise => Sub premise (unused)

我得到的教训是:

  • 不要存储任何数字。
  • 尽可能将国家和行政区域存储为 ISO 代码。
  • 当您不知道时,请不要要求字段。有些国家可能不会使用你认为理所当然的字段,甚至像 localitythoroughfare这样的基本字段。

目前,我正在开发一个国际电子商务网站。

它应该涵盖这个世界上几乎所有的地址,如下所示:

*****************************************************************
Type            Field name    Displayed name in your form
*****************************************************************
INT             id (PK)
VARCHAR(100)    building      Apt, office, suite, etc. (Optional)
VARCHAR(100)    street        Street address
VARCHAR(100)    city          City
VARCHAR(100)    state         State, province or prefecture
VARCHAR(100)    zip_code      Zip code
VARCHAR(100)    country       Country
*****************************************************************