国际地理地址如何存储在关系数据库中?

鉴于将国际地理地址存储在关系表中的任务,什么是最灵活的模式? 地址的每一部分应该分解到自己的领域,还是应该更像自由文本?

将不同格式的地址分隔成不同的表格是否有意义? 例如,为USAAddress,CanadianAddress,UKAddress …添加一个表格?

我将从我的博客文章 – 地址存储课程中总结我的想法。

在我目前的项目上(我为一家物stream公司工作),我们正在储存国际地址。 我在这部分数据库的devise中已经研究了世界各地的地址。 有很多不同的格式。 在西方世界,我们倾向于使用相当统一的格式 – 有一些差异,但主要是:

  • 街道号码 – 数字
  • 房屋或build筑物名称 – [VarChar – 在英国,一些房屋/build筑物是通过名称而非数字来标识的]
  • 街道号码后缀 [VarChar,尽pipe在大多数情况下,字符(1)就足够了]
    • A,B等
  • 街道名称 [VarChar]
  • 街道types [VarChar或Int如果您有StreetTypes表]
    • 到目前为止,我已经在英语世界里find了262种独特的types,可能还有更多,不要忘记其他语言,如Strasse,Rue等。
  • 街道方向 [VarChar(2)]
    • N,E,S,W,NE,SE,NW,SW
  • 地址types [VarChar或Int,如果您有AddressTypes表]
    • 邮政信箱
    • 公寓
    • build造
    • 地板
    • 办公室
    • 套房
    • 等等…
  • 地址types标识符 [VarChar]
    • 即箱号,公寓号,楼层号记住公寓号码和办公室有时有字母数字信息 – 如1A
  • 当地市 [VarChar或诠释,如果你有一个市政表]
    • 例如,如果你的小村庄出现在镇前的地址。
  • 城市/城镇 [VarChar或Int,如果您有城市表]
  • 治理区 [VarChar或Int如果你有一个区表]
    • 州(美国)
    • 省(加拿大)
    • 联邦区(墨西哥)
    • 郡(英国)
    • 等等…
  • 邮政区 [VarChar]
    • Zip(美国)
    • 邮政编码(加拿大,墨西哥)
    • 邮政编码(英国)
  • 国家 [VarChar或Int如果你有国家表]

这似乎涵盖大多数国家,但字段的sorting可能会显示不同。 您可以在http://www.bitboost.com/ref/international-address-formats.html#Formatsfind显示格式列表;

例如,在许多国家,邮政编码落在城市名称之前,街道号码落在街道名称之后。 在加拿大,美国和英国,街道号码位于街道名称的前面,邮政编码(或ZIP)位于城市名称的后面。

在回答你关于将地址分隔到不同国家的问题时,我不会提出这个build议,只会在其他方面让生活变得更加困难,例如报告。 我提供的格式涵盖了美国,加拿大,墨西哥和英国的物stream数据库中的所有地址,没有任何问题。 它也涵盖了我们所有的欧洲,中国,日本和马来西亚的地址。 我不能为其他国家说话,但我还没有存储这些领域不支持的国家的地址。

我不build议使用其他人build议的地址1,地址2,地址3格式,因为从字母数字string中分析地址信息并不像看起来那么简单 – 特别是如果数据input不正确,由于错误的信息,错字,拼写错误等。如果你分开你的领域,你可以使用距离algorithm来检查可能的含义,使用概率检查街道名称对邮政编码和街道号码或检查省市对街道名称等。当你有一个string表示你的整个街道地址时,做任何这样的事情。 这不是一个微不足道的问题。

地址数据库上的QA是一个令人头痛的时期。 在这个领域简化您的生活的最简单的方法是确保所有的字段只保存一个信息,可以在入境时自动validation正确的信息。 概率,距离algorithm和正则expression式可以检查input的有效性,并向用户提供有关其错误的反馈,并提出合适的更正。

需要注意的一点是道路名称也是街道types – 如果您覆盖加拿大,则需要了解多伦多的“Avenue Road”,如果您使用Address1,2 ,3格式。 这也可能发生在其他地方,虽然我不知道他们 – 这个单一的实例就足以让我尖叫WTF?

小心不要过分分析地址格式。 当你这样做的时候,你很可能会制定一个大多数用户需要解决的规范,有效地强迫他们使用错误的字段,或者只填写主要字段并忽略额外字段。

保持简单。

BenAlabaster提到的街道types在开始使用不同于隔离语言(如英语或西class牙语)的语言时会导致问题。

为了向您展示在野外可能遇到的困难:阿姆斯特丹的“Henriette Roland Holststraat”,由“Henriette”+“Roland Holst”+“straat”组成,可以简写为“Roland Holststraat”或“罗兰Holststr。“,或拼写为”HRHolststr“。 或“Henriette Roland-Holst straat”,取决于天气。 除非你在地球上每个国家都有最新的街头登记,否则你将无处可去。

最后,请注意,在一些多语言国家,名称可能会因语言而异! 例如在布鲁塞尔,许多街道上都有法国荷兰的名字:“Avenu du Port”和“Havenlaan”,取决于收件人的首选语言。 (谷歌地图交替显示两个名字,只是为了安全起见。)

你可以尝试在这里devise各种巧妙的技巧,但是是销售代表。 去了解这个?

这取决于你想要做什么。

我发现,如果将地址用于其他目的(如对USPS数据进行validation或从UPS / FEDEX获取运费),则将地址用于其他用途会更容易。

以下是我通常用于地址的内容:

  • 地址栏1
  • 地址线2
  • 地址线3
  • 地区
  • 邮政编码
  • 国家

回应编辑:对于大多数情况下,我没有看到使用。 上面列出的表对于大多数国家的地址都有足够的字段(足够通用)。

地址

作为极好的答案@BenAlabaster所提供的极性,你可以简单地拥有:

address TEXT(300) postal_code VARCHAR(15) country_code VARCHAR(2) 

您的客户端表单布局仍然可以像您认为的那样复杂(或者使用多行input,用户可以手动input地址)。 然后,您可以在必要时在地址中添加换行符。

国家

你的国家表格如下所示:

 country_code VARCHAR(2) country_name VARCHAR(255) 

此外,您可以有以下之一:

 postal_code_required TINYINT(1) postal_code_regex VARCHAR(255) NULL DEFAULT NULL 

然后使用下面的列表来devise你的国家表格:

  • 维基百科:ISO 3166-1 alpha-2
  • GitHub:没有邮政编码的国家
  • GitHub:MySQL国家列表
  • 邮政编码正则表

对于这个问题的任何人来说,这是一个轶事:

我作为一个在欧洲,亚洲,北美洲生活和工作过的人说话。 根据我的经验以及与我合作的人员的经验,使用以下系统的系统变得更加容易:

  1. 提供三行,我将input一个地址。 当我按照他们的方式逐字input时,将这三行传送到您当地的邮局。 让我用我想要的任何字符集; 使用UTF-8或更好的东西。
  2. 如果您的系统有业务需求,需要我指定特定的信息(如邮政编码,州,州等),请单独询问。 根据业务需求,我的意思是分析等。 这些信息不应该与您当地的邮政服务共享(除非我也碰巧把相同的信息写入上述第1点的三条线之一)。
  3. 有一个下拉,要求我指定在上面的第1点,也许是国家行提供的地址I的分类位置。
  4. 如果你必须parsing我在第1点提供的信息,使用我对第3点的回答来select正则expression式。 针对点1中的信息运行该正则expression式来parsing它。 尝试使用正则expression式的输出填充Point 2的用户界面元素。 如果我更正了自动填充的信息 – 使用我改变它来改善你的正则expression式的事实。 同样,尽可能给我一个机会来检查和纠正你的正则expression式的输出:没有人比我更了解我想要传达的信息。

这样构build的系统,我发现,使我的生活最简单。 特别是当我将邮件发送到您的公司实际上没有function内部知识的邮政系统时。

如果贵公司对特定的邮政系统有内部知识,请使用我在第3点的select来通知您向我展示哪个视图。 很多人都知道美国邮政系统在包装上的期望, 如果我在第3点select美国,请随意使视图适合美国地址。 如果我select一个你的公司什么都不知道的国家 – 展示一个通用的三条线,让我rest一下; 不要强迫我使用ASCII。

让我们成为现实 – build立一个完整的,全面的全球邮政系统(公共和私人)的百科全书数据库,如果不是不可能的话,充其量也是一项艰巨的任务。 例如,邮政系统只有当地的最后一英里的航空公司才真正知道地址的位置。 有时能够通过包装上的该载体的笔记是非常有用的。 把每个边缘案例载体的本地知识映射到你的数据库中确实是一个不可能完成的任务。

只要问哥德尔。 (然后问自己,如果你试图用一个公理系统来模拟一个话语的宇宙,给定或者采取像集合论或者关系代数这样的算术。

唯一的办法是把它们分成:

 Name varchar, Title varchar, StreetAddress varchar, StreetAddressLine2 varchar, zipCode varchar, City varchar, Province varchar, Country lookup 

因为几乎每个国家都有自己的地址数据标准,evey国家有不同的邮编格式。
你可以在我的post中find一个类似问题的小样本。

这对于每个国家的地址都是没有意义的,因为有些国家的地址约定很less。 一些stream行的公约包括没有小村庄的街道,只有村名和号码,而街道是在大城市的地址。 我了解到,在匈牙利首都布达佩斯,很less有同名的街道(你根据城市的地区号区分),而其他城市没有这样的地址(匈牙利的人可能确实确认这是真的)。 所以地址格式的总数将会被这个国家的地址格式的数量乘以numer_of_countries …可以用不同的表格完成,但这将是一件可怕的工作。

Ben Alabaster的答案的评论:要格式化基于国家的地址,您可以使用一个格式表,每个国家的列的sorting作为单独的行。

  • AddressFormat(CountryCode,FieldName,FieldOrder)

字段顺序也可以编码,以使用复杂的网格布局。

按国家分隔地址是毫无意义的。 随着国家数量的增加,这将是混乱的,如果你想find国际客户这么说的所有地址,你就会陷入麻烦。 由Ben提出的地址types也可能导致含糊不清的情况,如果您的地址既有build筑物号码又有公寓号码。 我可以在一个公寓大楼里,每栋大楼都有不同的名字。 这在印度很常见。

我知道这是一个很老的话题,已经有了答案,但是我还以为我会投两分钱。 这完全取决于您的项目目标以及您希望目标用户input地址的方式。 本的build议将允许您准确地parsing地址,但另一方面可能会使用户数据input过程更长(可能更令人沮丧)。 Stephen Wrighton的build议比较简单,用户可以更容易input地址。

我还看到一些模型,只有一个“地址”列,可以在保存城市,国家,地区等的同时在一列中捕获典型的街道号,types,街道名称,单位/公寓号等。在其他栏内。 与斯蒂芬的模型类似,地址1,地址2和地址3全部合并成一列。

我的观点是,最灵活的模型往往是那些限制最less的,取决于你对灵活性的解释。

我使用https://github.com/commerceguys/addressing库格式国际地址,他们使用这些元素:;

 Country Administrative area Locality (City) Dependent Locality (in: BR, CN, IR, MY, MX, NZ, PH, KR, ZA, TH) Postal code Sorting code Address line 1 Address line 2 Organization Recipient 

如果你想parsing街道(名字,门牌号码…),这不会有帮助。

顺便说一句。 如果您正在寻找一个多语言国家列表: https : //github.com/umpirsky/country-list