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

时间:2009-07-21 15:01:54

标签: database-design street-address

鉴于将国际地理地址存储在关系表中的任务,最灵活的架构是什么?地址的每个部分都应该分解到自己的字段中,还是应该更像是自由文本?

将不同格式的地址分成不同的表有什么意义吗?例如,有一个表用于USAAddress,CanadianAddress,UKAddress ......?

9 个答案:

答案 0 :(得分:85)

我将在博客文章A lesson in address storage中总结我的想法。

在我目前的项目[我为物流公司工作]我们存储国际地址。我在数据库的这一部分的设计中研究了世界各地的地址。有很多不同的格式。在西方世界,我们倾向于使用相当统一的格式 - 一些差异,但它们主要是:

  • 街道号码 - 数字
  • 房屋或建筑物名称 - [VarChar - 在英国,某些房屋/建筑物按名称而非数字标识]
  • 街道号码后缀 [VarChar,尽管在大多数情况下,Char(1)就足够了]
    • A,B等
  • 街道名称 [VarChar]
  • 街道类型 [如果您有街道类型表,则为VarChar或Int]
    • 到目前为止,我在英语世界找到了262种独特的类型,可能还有更多,并且不要忘记其他语言,即Strasse,Rue等。
  • 街道方向 [VarChar(2)]
    • N,E,S,W,NE,SE,NW,SW
  • 地址类型 [如果您有AddressTypes表,则为VarChar或Int]
    • 邮政信箱
    • 公寓
    • 建筑
    • 地板
    • 办公室
    • 套件
    • 等...
  • 地址类型标识符 [VarChar]
    • 即。箱号,公寓号码,楼层号码记住公寓号码和办公室有时会有字母数字信息 - 如1A
  • 地方市政当局 [VarChar或Int如果您有市政府表格]
    • 例如,如果您的小村庄/村庄出现在镇前的地址中。
  • 城市/城镇 [如果您有城市表,则为VarChar或Int]
  • 管理区 [VarChar或Int,如果您有区域表]
    • 州(美国)
    • 省(加拿大)
    • 联邦区(墨西哥)
    • 郡(英国)
    • 等...
  • 邮政区域 [VarChar]
    • Zip(美国)
    • 邮政编码(加拿大,墨西哥)
    • 邮政编码(英国)
  • 国家/地区 [如果您有国家/地区表格,则为VarChar或Int]

这似乎涵盖了大多数国家/地区,但字段的顺序可能会以不同方式显示。您可以在http://www.bitboost.com/ref/international-address-formats.html#Formats

找到显示格式列表

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

在回答你关于将地址分成不同国家的问题时,我不建议,只会使其他领域的生活更加艰难 - 例如报道。我提供的格式涵盖了我们的物流数据库中的所有地址,其中包括美国,加拿大,墨西哥和英国,没有任何问题。它还涵盖了我们所有的欧洲,中国,日本和马来西亚地址。我不能代表其他国家发言,但我还没有必要存储这些字段不支持的国家/地区的地址。

我不建议使用其他人建议的Address1,Address2,Address3格式,并在许多数据库中看到,因为从字母数字字符串中解析地址信息并不像最初看起来那么简单 - 特别是如果数据不是' t由于错误信息,拼写错误,拼写错误等而输入正确。如果您将字段分开,则可以使用距离算法检查可能的含义,使用概率检查街道名称与邮政编码和街道编号,或检查省和城市的街道名称当你有一个字符串表示你的整个街道地址时,尝试做任何一件事。任何想象力都不是一件小事。

地址数据库上的质量保证是一个令人头疼的问题。简化此区域生活的最简单方法是确保所有字段仅包含一条信息,可在入口时自动验证为正确。概率,距离算法和正则表达式可以检查输入的有效性,并向用户提供关于他们的错误是什么的反馈,并建议适当的更正。

需要注意的一个警告是道路的名称也是街道类型 - 如果你正在覆盖加拿大,你需要注意多伦多的“大道路”,如果你使用的话,它会让你大吃一惊地址1,2,3格式。这可能也发生在其他地方,虽然我不知道它们 - 这个单一实例足以让我尖叫WTF?!

答案 1 :(得分:19)

小心不要过度分析地址格式。当你这样做时,你很可能最终得到大多数用户围绕工作的规范,有效地迫使他们使用错误的字段,或只填充主要字段并忽略额外的字段。

保持简单。

当你开始使用与英语或西班牙语等隔离语言不同的语言时,BenAlabaster提到的StreetType会引起问题。

向您展示在野外会有多糟糕的事情:阿姆斯特丹的“Henriette Roland Holststraat”,由“Henriette”+“Roland Holst”+“straat”构成,可简称为“Roland Holststraat” ,或“Roland Holststr。”,或拼错为“HRHolststr”。或“Henriette Roland-Holst straat”,视天气而定。除非你有一个地球上每个国家的最新街道登记册,否则你将无处可去。

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

你可以尝试在这里设计各种聪明的技巧,但是销售代表。会明白这个吗?

答案 2 :(得分:8)

这取决于你想用它做什么。

我发现如果将地址用于其他目的(例如针对USPS数据的验证或从UPS / FEDEX获得运费),它们总是更容易分开。

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

  • 地址第1行
  • 地址第2行
  • 地址第3行
  • 区域
  • 邮政编码
  • 国家/地区

响应编辑:在大多数情况下,我看不到使用情况。上面列出的表格对于大多数国家/地区的地址都有足够的字段(并且足够通用)。

答案 3 :(得分:5)

地址

与@BenAlabaster提供的优秀答案相反,您可以简单地:

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

您的客户端表单布局仍然可能是您认为合适的复杂(或使用多行输入,用户可以手动键入其地址)。然后,您可以在必要时在地址中添加换行符。

国家

您的国家/地区表格如下:

country_code  VARCHAR(2)
country_name  VARCHAR(255)

此外,您可以一个以下内容:

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

然后使用以下列表设计您的国家/地区表格:

答案 4 :(得分:3)

这是一个偶然发现这个问题的人的轶事:

我是一个在很多大陆(欧洲,亚洲,北美)生活和工作过的人。根据我的经验以及与我合作的人的经验,我们使用以下系统更容易:

  1. 提供三行我将输入一个地址。将这三行传递到您当地的邮政服务,我会逐字输入。让我使用我想要的任何字符集;使用UTF-8或更好的东西。
  2. 如果您的系统有业务需求需要我指定特定信息(例如邮政编码,县,州等),请单独询问。根据业务需求,我的意思是分析;这些信息不应该与您当地的邮政服务共享(除非我也碰巧将相同的信息写入上面第1点的三条线之一)。
  3. 有一个下拉列表,要求我指定我在上面第1点的行中提供的地址的分类位置,也许是国家。
  4. 如果您必须解析我在第1点的行中提供的信息,请使用我对第3点的回答来选择正则表达式。针对Point 1中的信息运行该正则表达式来解析它。尝试使用正则表达式的输出填充Point 2的用户界面元素。如果我更正了自动填充的信息 - 请使用我更改它以改善正则表达式的事实。同样,尽可能让我有机会审查并纠正你的正则表达式的输出:没有人比我更清楚我想要传达的信息。
  5. 我发现,这样建造的系统让我的生活变得最轻松。特别是当我向邮政系统发送邮件时,你的公司几乎没有任何内部知识。

    如果您的公司确实掌握了有关特定邮政系统的内部知识,请使用我在第3点中的选择来告知您向我显示的视图。很多人都知道美国邮政系统对包装的期望;如果我在第3点选择US,请随意使视图看起来适合美国地址。如果我选择一个你的公司什么都不知道的国家 - 显示一个通用的三行,让我做其余的事情;不要强迫我使用ASCII。

    让我们在这里真实 - 建立一个完整的,百科全书的全球邮政系统(公共和私人)数据库,这是一项艰巨的任务,如果不是不可能的话。例如,有邮政系统,其中只有本地的最后一英里航空公司确实知道地址所在的位置。有时能够在包装上将注释传递给该载体是非常有用的。将每个边缘案例载体的本地知识映射到数据库中确实是一项不可能完成的任务。

    请问哥德尔。 (然后问问自己,你是否试图使用公理系统来模拟话语世界,给出或采取某种算法,如集合论或关系代数。)

答案 5 :(得分:1)

Ben Alabaster的答案评论: 要根据国家/地区格式化地址,您可以使用格式表,其中每个国家/地区的列的顺序为单独的行。

  • AddressFormat(CountryCode,FieldName,FieldOrder)

可以对字段顺序进行编码以使用复杂的网格布局。

按国家/地区分隔地址毫无意义。随着国家数量的增加,这将是混乱的,如果你想找到国际客户的所有地址,你将陷入困境。 如果您的地址同时包含建筑物编号和公寓编号,那么Ben建议的地址类型也可能导致含糊不清。我可以在一个公寓大楼里,每个建筑都有不同的名字。这在印度很常见。

答案 6 :(得分:1)

我使用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

如果您想要解析街道(姓名,门牌号......),这无济于事。

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

答案 7 :(得分:0)

唯一的方法是将它们分成:

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

因为几乎每个国家都有自己的地址数据标准,而evey国家的邮政编码格式不同。
您可以从类似问题的my post中获得一小部分问题。

将每个国家/地区的地址分开是没有意义的,因为有些国家/地区的地址约定很少。一些受欢迎的公约包括在小村庄没有街道,只有村名和号码,而街道在大城市的地址。我了解到,在匈牙利的首都 - 布达佩斯,几乎没有同名的街道(你根据城市的区号区分它们),而其他城市没有这样的地址(来自匈牙利的人实际上可能确认这是否属实)。因此,地址格式的总数将是numer_of_countries乘以该国家/地区的地址格式数量...可以使用不同的表格来完成,但这将是一项非常糟糕的工作。

答案 8 :(得分:0)

我知道这是一个已经回答过的非常古老的话题,但我认为我也会投入两分钱。这完全取决于您的项目目标以及您希望目标用户输入地址的方式。 Ben的建议将允许您准确地解析地址,但另一方面可能会导致更长(可能更令人沮丧)的用户数据输入过程。 Stephen Wrighton的建议更简单,因此用户可以更容易地输入地址。

我还看到一些模型只有一个“地址”列,可以在一列中捕获典型的街道号码,类型,街道名称,单位/公寓号码等,同时保留城市,乡村,地区等等在其他列中。与Stephen的模型类似,除了Address1,Address2和Address3之外,所有这些都合并为一列。

我的观点是,最灵活的模型往往是限制性最小的模型,具体取决于您对灵活性的解释。