【问题标题】:How Bad is this Database for Address?这个地址数据库有多糟糕?
【发布时间】:2012-06-23 11:14:58
【问题描述】:

我还是数据库、规范化等方面的新手,我可能需要一些帮助。这里附上我的数据库结构的一部分,我认为我的方法是个坏主意。在这里,我们的国家可以分为不同的省,所有的城市/城镇都在一个特定的省和一个描笼涯(我猜最接近外行人的术语是地区)。因此,如果在我们国家的所有地方,无论您身在何处,您都必须拥有特定的描笼涯、城市/城镇和省。我所做的是我使用外键来引用表格 barangay、城市/城镇、省。这是个坏主意吗?

如果我创建一个tblCustomer_AddressCountry_ID: Int FKProvince_ID: Int FKCityTown_ID: Int FKBaranggay_ID: Int FKtblCustomer 分开,会有什么不同?

谢谢!

tblCustomer(
  Customer_Id: Int PK
  Customer_FName: String
  Customer_MName: String
  Customer_LName: String
  Country_ID: Int FK
  Province_ID: Int FK
  CityTown_ID: Int FK
  Baranggay_ID: Int FK
  Additional_Address_Details: String
 )
tblCountry(
  Country_Id: Int PK
  Country_Name: String
)
tblProvince(
  Province_Id: Int PK
  Province_Name: String
)
tblCityTown(
  CityTown_Id: Int PK
  CityTown_Name: String
)
tblBarangay(
  Barangay_Id: Int PK
  Barangay_Name: String
)

* 编辑:顺便说一句,我忘了提。我项目的一部分是生成报告,所以我想到的是跟踪位置。所以我想为描笼涯、城市/城镇、省份设置单独的表格,以使每个人都独一无二。

【问题讨论】:

  • 欢迎使用 StackOverflow:如果您发布代码、XML 或数据示例,在文本编辑器中突出显示这些行并单击“代码示例”按钮 ({ } ) 在编辑器工具栏上很好地格式化和语法高亮它!那么你也不需要那些乱七八糟的 <br> 标签!

标签: sql database structure normalization street-address


【解决方案1】:

相当糟糕,因为您必须维护国家、城市和地区的可用选项。

就个人而言,我只是创建了一个addresses 数据库表,其中地址组件的字段符合 hCard 微格式:

CREATE TABLE IF NOT EXISTS `addresses` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `extended_address` varchar(128) DEFAULT NULL,
  `street_address` varchar(128) NOT NULL,
  `locality` varchar(128) NOT NULL,
  `region` varchar(128) DEFAULT NULL,
  `postal_code` varchar(128) DEFAULT NULL,
  `country_name` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
)

【讨论】:

  • 我不确定它是否“相当糟糕”——这取决于它的使用方式。如果有国家和省的 GUI 下拉菜单,将它们放入单独的表中是有意义的。即使对于城市等,也可能需要标准化。
  • 国家名称变化的速度比您想象的要快,更不用说各种不同的语言了。此外,我还必须考虑如何将我自己的地址放入该架构中。
  • 是的。我是这样想的,有下拉菜单等等。无论如何,我仍在尝试将所有响应拼凑在一起。感谢您的回复!
  • @Remou 只要您只想跟踪当前地址,更改国家名称就不是问题。您只需运行一个简单的更新,更改表格中的国家/地区名称。你当然是对的,在 3NF 中你应该把它分开。但是,如果它真的无关紧要(例如,这将仍然是唯一使用国家/地区的地方,并且您不需要跟踪历史地址),那么您只是在产生不必要的连接等。
  • @janb 我可以看到你来自哪里,我在很大程度上同意你的看法,但在我自己的国家,通常情况下,国名可以使用两种语言中的一种,这意味着按国家/地区进行分析可能会变得复杂。
【解决方案2】:

在我看来,一个城市或省将存在一个描笼涯,一个省将存在一个城市,一个国家将存在一个省。在结构中,您有一个位置表,位置类型为 Barangay、City、Province、Rural 或 Country,并且 parentID 指向层次结构中的父位置。然后您的客户有一个位置 ID 指向层次结构中的任何位置。可以将新位置添加为城市、省(农村)地区或国家中的现有位置。表格如下所示:

tblLocation(
LocationID int PK,
ParentID int FK references tblLocation LocationID,
LocationType int FK references tbllocationTypes,
LocationName
)

无法将此添加为注释,因此这里有一个更完整的实现:

CREATE TABLE LocationType
(
    LocationTypeID int not null primary key,
    LocationTypeName varchar(20) not null unique
)
GO
CREATE TABLE Location (
    LocationID int not null primary key,
    ParentId int null references Location (LocationID),
    LocationName varchar(100),
    LocationTypeID int not null references LocationType (LocationTypeID)    
)
GO
CREATE Table Customer (
    CustomerID int not null primary key,
    FirstName varchar(50),
    MiddleName varchar(50),
    LastName varchar(50),
    LocationID int references Location (LocationID)
)
GO
CREATE TABLE City(  
    CityID int not null primary key references Location (LocationID),
    PostCode varchar(20) not null
)
GO
CREATE VIEW DetailedLocation AS 
    SELECT L.*, C.PostCode FROM Location AS L
    LEFT OUTER JOIN City AS C
    ON C.CityID = L.LocationID

【讨论】:

  • 为什么我没有想到这一点……当然它必须有一个层次结构。例如,我的可以在一个描笼涯,但在一个不应该位于的城市/城镇中(简而言之,在不同的城市/城镇下的描笼涯)。谢谢
  • 我认为这种方法只是提出问题。您假设没有任何不同的位置类型需要它们自己的属性。如果你突然需要城镇有一个邮政编码,你会怎么做?向 tblLocation 添加字段?大多数行都必须为空,这很糟糕。
  • 就在我认为这种方法有意义的时候。我要疯了,为什么我首先选择获得这个学位?哈哈,这是我忘记考虑的另一个变量 - 邮政编码。我还计划将其用于固定电话号码前缀的“智能”识别。我还不如不去。
  • @janb:添加一个名为 town 的实体非常简单,该实体有一个邮政编码,以及一个与该位置的主键相关的主键。 IE。城镇是一个位置。对于属于任何其他实体类型的任何附加信息也是如此。都是位置,层次合适。
  • 但是基于位置的类型检索有关位置的信息变得不必要的复杂恕我直言。您必须根据类型查找某个表,或者不查找某些类型。基本上你创造了一个幻数。
【解决方案3】:

问题在于您没有以正确的方式处理地址。如果您真的不需要完整地址(或者我只是在这里遗漏了这个?),那么在客户表中只有一个 Baranggay 字段将是“好的”。在任何其他情况下,您都应该有一个地址表,并且只需在客户表中引用 addressID。当然,除非客户应该能够拥有多个地址,在这种情况下,您应该为这种 m:n 关系引入一个 CustomerAddressRel 表。

无论如何,在这里将地址拆分为多个字段和/或表是毫无意义的。一个特定的 barangay 将永远只属于一个城镇,那个城镇属于一个省,那个省属于一个国家(国家?如果这是关于多个国家,你需要不同的格式,因为 barangay 不是一个国际概念!)。因此,跟踪地址中的 baranggay 并有一个不同的表来保存 baranggay 所属的城镇和省份确实足够了。

很抱歉,文字太长了,但我觉得如果我提出一个修改后的方案,它对你一点帮助都没有。您需要了解某些决策的原因,然后根据您当前的数据集和预期范围做出最佳决策。如果您有可能走向国际,请确保数据方案现在已准备好。

编辑:

好吧,我认为还是放下它是最好的。如果您想要面向未来且灵活,至少只要您限制菲律宾人并且描笼涯属于一个城镇:

tblCustomer(
    Customer_ID: Int PK
    Customer_FName: String
    Customer_MName: String
    Customer_LName: String
)

tblCustomerAddressRel(
    Customer_ID: Int FK
    Address_ID: Int Fk
    Type: (Mailing, Billing, Historic,...)
)

tblAddress(
    Address_ID: Int PK
    Baranggay_ID: Int FK
    Additional_Address_Details: String (<< this looks like a bad idea btw)
)

tblCountry(
    Country_ID: Int PK
    Country_Name: String
)

tblProvince(
    Province_Id: Int PK
    Province_Name: String
    County_ID: Int FK
)
tblCityTown(
    CityTown_ID: Int PK
    CityTown_Name: String
    Province_ID: Int FK
)
tblBarangay(
    Barangay_ID: Int PK
    Barangay_Name: String
    CityTown_ID: Int FK
)

【讨论】:

  • 谢谢。如果我不太清楚,我很抱歉,可能是因为我的英语。我该如何解释,这里的描笼涯名称不是唯一的,它可以从一个城市使用到另一个城市;只有城市/城镇,省份是独一无二的。当我将它们拆分为多个表时,我的想法是让它们在我提取数据时更容易识别(至少我认为会如此),正如@sleske 所提到的,我计划使用一个下拉菜单。我不是在这里混蛋,我只是想了解。
  • 我正准备将@Kell 的层次结构理念融入我最初的方法中,看看它是否合适,我想这就是你所做的。尽管多个地址非常整洁,但我根本没有看到,谢谢 janb ...我在这里学到了很多东西。想像 Additional_Address_Details 看起来很糟糕,即使只是看一下糟糕的命名。哈哈我的想法只是为了存储更具体的地址详细信息(如街区、街道号码)。在能够访问特定客户的描笼涯、城市、省地址之后,我更喜欢。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 2021-04-05
  • 2010-11-24
  • 2011-01-01
  • 1970-01-01
相关资源
最近更新 更多