在数据库中一致且全面的地址存储的最佳实践
是否有最佳实践(甚至标准)以一致且全面的方式将地址存储在数据库中?
更具体地说,我相信在此阶段,地址存储有两种情况:
- 我们只需要将地址与人,建筑物或者任何物品(最常见的情况)相关联即可。然后,带有文本列(地址1,地址2,邮政编码,城市)的平面表就足够了。这不是我感兴趣的情况。
- 我们想对地址进行统计:在特定街道,城市或者城市中有多少个项目?然后,我们要避免任何形式的拼写错误,并确保一致性。我的问题是关于这种特定情况的最佳实践:建立一致的地址数据库的最佳方法是什么?
特定国家/地区的设计/解决方案将是一个不错的开始。
答案:这个问题似乎还没有一个完美的答案,但是:
- 正如Hank所建议的那样,xAL是与弹出的全球标准最接近的东西。但是,这似乎是一个过大的杀伤力,而且我不确定很多人会希望在他们的数据库中实现它。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
- 为了开始自己的设计(针对特定国家/地区),Dave与万国邮政联盟(UPU)网站的链接是一个很好的起点。
- 对于法国,有一个地址规范(非官方的,但实际上是标准),该名称带有AFNOR XP Z10-011(仅法语)的可爱名称,必须付费。法国的UPU说明就是基于此规范。
- 我碰巧找到了瑞典的同等标准:SS 613401.
- 在欧洲范围内,已经做出了一些努力,形成了EN 14142-1规范。它可以通过CEN国家成员获得。
解决方案
标准化数据库架构,我们将拥有完美的结构以确保正确的一致性。这就是为什么:
http://weblogs.sqlteam.com/mladenp/archive/2008/09/17/Normalization-for-databases-is-like-Dependency-Injection-for-code.aspx
正如我们所建议的,我将使用"地址"表,并将其基于xAL跟踪的数据。
在英国,Royal Mail有一种叫做PAF的产品
但是,这为每个地址提供了唯一的密钥,但是有很多问题需要跳过。
如果需要一致性,我基本上会看到2个选择:
- 数据清理
- 基本数据表查询
广告1.我使用SAS系统,并且SAS Institute提供了一种数据清理工具,该工具基本上会对数据进行一些检查和验证,并建议将" Abram Lincoln Road"和" Abraham Lincoln Road"合并到同一条街上。我还认为它利用了包含城市邮政编码匹配等的国家数据库。
广告2. 我们建立了一个选择列表(即基本数据),添加新条目的人员从基本数据中的现有条目中进行选择。在事实表中,我们存储街道名称的键,而不是街道名称本身。如果我们检测到拼写错误,则只需在基本数据中对其进行更正,并通过密钥关系对所有实例进行更正。
请注意,这些选项并不互相排斥,我们可以同时使用两种方法。
我之前问过类似的问题:动态联系信息数据/设计模式:这在任何方面都可行吗?
简短的答案:在数据库中存储地址或者任何联系方式很复杂。上面的可扩展地址语言(xAL)链接包含一些有趣的信息,这些信息与我所遇到的标准/最佳实践最接近...
在美国,我建议选择"国家地址变更"供应商,并根据他们返回的数据对数据库进行建模。
通常,关于地址构造的权限是邮政服务,因此,一开始,我将检查我们所经营的主要市场中邮政服务使用的数据元素。
有关国际邮政地址格式的非常具体和详细的信息,请参见万国邮政联盟的网站:http://www.upu.int/post_code/en/postal_addressing_systems_member_countries.shtml
我也一直在考虑这个问题。到目前为止,这是我的松散想法,我想知道其他人的想法。
Google和Yahoo的地理编码服务都使用xAL(及其姊妹名称,其中包括XNAL),使其具有一定的分量。但是由于可以用许多不同的方式在xAL中描述相同的地址(某些方式比其他方式更具体),因此我看不出xAL本身是数据存储可接受的格式。但是,可以使用其某些字段名称,但实际上,在我公司运送到的16个国家/地区中,唯一可以使用的基本格式如下:
enum address-fields { name, company-name, street-lines[], // up to 4 free-type street lines county/sublocality, city/town/district, state/province/region/territory, postal-code, country }
映射到单个数据库表很容易,只需要在大多数列上使用NULL即可。看来这就是Amazon和许多组织实际存储地址数据的方式。因此,剩下的问题是我该如何在程序员和任何GUI代码都易于使用的对象模型中对此建模。我们是否具有基本的"地址"类型,以及每种地址类型的子类,例如"美国地址","加拿大地址","德国地址"等等?这些地址类型中的每一种都将知道如何格式化自身,并且可选地将对字段的验证有所了解。
他们还可以返回有关每个字段的某种类型的元数据,例如以下伪代码数据结构:
structure address-field-metadata { field-number, // corresponds to the enumeration above field-index, // the order in which the field is usually displayed field-name, // a "localized" name; US == "State", CA == "Province", etc is-applicable, // whether or not the field is even looked at / valid is-required, // whether or not the field is required validation-regex, // an optional regex to apply against the field allowed-values[] // an optional array of specific values the field can be set to }
实际上,除了为每个国家/地区使用单独的地址对象外,我们还可以采用一种稍微面向对象的方法,即使用一个避开.NET属性并使用AddressStrategy
来确定格式和验证规则的Address对象:
object address { set-field(field-number, field-value), address-strategy } object address-strategy { validate-field(field-number, field-value), cleanse-address(address), format-address(address, formatting-options) }
设置字段时,该"地址"对象将在其内部的"地址策略"对象上调用适当的方法。
使用SetField()方法而不是使用具有getter和setter的属性的原因是,这样,代码实际上更容易以通用方式实际设置这些字段,而无需借助反射或者switch语句。
我们可以想象该过程是这样的:
- GUI代码调用工厂方法或者类似方法来基于国家/地区创建地址。 (然后,国家/地区下拉列表是客户选择的第一件事,或者根据文化信息或者IP地址为其预先选择了一个不错的猜测。)
- GUI调用address.GetMetadata()或者类似方法,并接收如上所述的AddressFieldMetadata结构的列表。它可以使用该元数据来确定要显示的字段(忽略那些将" is-applicable"设置为" false"的字段),标记哪些字段(使用" field-name"成员),以特定顺序显示这些字段。 ,并对该数据执行粗略的表示层验证(使用" is-required"," validation-regex"和" allowed-values"成员)。
- GUI使用"字段编号"(对应于上面的枚举)及其给定值调用" address.SetField()"方法。然后,"地址"对象或者其策略可以在这些字段上执行一些高级地址验证,调用地址清除器等。
如果我们想使"地址"对象本身在创建后就像一个不可变的对象,则上述内容可能会有一些变化。 (我可能会尝试这样做,因为" Address"对象实际上更像是一个数据结构,并且可能永远不会有任何与之关联的真实行为。)
这有道理吗?我在OOP路径上走得太远了吗?对我来说,这代表了一种非常明智的折衷,既要过于抽象以至于实施几乎不可能(xAL),也要严格按照美国的偏见进行。
2年后更新:我最终使用了一个与此类似的系统,并在我已停业的博客上写了有关此系统的信息。
我觉得这种解决方案至少在电子商务世界中,可以在传统数据和关系数据存储之间找到适当的平衡。