【发布时间】:2017-12-13 18:53:24
【问题描述】:
我有一个意见问题,但同时可能有一个正确的答案。我正在尝试开发一套产品,并希望确保因为我自己在做,所以我第一次就做对了。我多次重写了架构,每次都认为它更好。然后我可能会遇到一些新想法,它要么需要在架构上进行大量工作,要么会破坏我的架构。
在大学里,我学会了“合理化”(我认为这是他们使用的词,可能有点离题)一个数据库,有 5 个级别。据我记得,3 级是最常见的。我知道这种做法是为了确保数据不会重复,为此,您必须将表分解为较小的表。并且取决于你打破它的程度,级别越高。好吧,我不知道我是否想要最高级别,但我知道我希望它尽可能高效。我已经使用了 4 年的 SQL Server 2000/2005/2008 和 2 年的 Oracle,使用 Informix 大约 6 个月(5 多年前),在这里或那里使用 mySQL 和大约 6 个月的 Access。我的首选是 SQL Server,但我希望架构在任一平台上都一样高效。
这是一些表的伪模式布局,然后我将解释我想要做什么。
Manufacturers
ManufacturerID (Identity)
ManufacturerName
ManufacturerStreetAddress
ManufacturerZipCodeID
...
ZipCodes
ZipCodeID (Identity)
ZipCode
ZipCodeStateID
...
States
StateID (Identity)
StateName
StateAbbreviation
...
Cities
CityID (Identity)
CityName
CityStateID
...
我很抱歉它只是一个伪模式,但这就是我现在所拥有的,因为我正在休息时在纸上进行设计,但在我走得太远之前有一个问题。我想做的是确保一切都正确地相互联系。我的信念是邮政编码属于一个州和一个城市,但没有一个城市属于任何一个邮政编码,它可能有很多。如果我将邮政编码放在制造商表中,我希望能够获得州和城市。但我不想在其他表中多次使用任何 ID。我的意思是在 ZipCodes 和 Cities 中拥有 StateID 的次数可能太多了。一个州可以有多个同名城市,多个州可以有同名城市。但我不确定我是否想要一个 CityNames 表,然后是一个 CityStates 表(CityNameID 和 StateID)。我很清楚有一些位置数据库可供购买,也许有些是免费的,我可以使用而且不必担心这一点。但是,我想努力理解这一点,因为我相信它会在未来帮助我进行架构设计,而且还因为如果需要更改任何内容,我希望拥有布局的可定制性。
问题:
- 这种伪模式看起来是正确的还是会更好(意见)?
- 它是否被称为“合理化”数据库,或者其他什么(将投票支持正确答案)?还有多远(意见)
- 还有一个用户表和其他包含地址的表(Teams、Capitols 等),如果理论上是正确的,那么伪模式也是这样的数据库的好计划(意见)?
感谢大家的宝贵时间,我会投票赞成任何彻底和连贯的答案。数据库专家或具有多年数据库经验的人优先,但我会听取所有答案。另外,我不确定这是否应该是一个社区 wiki,但我现在没有将它标记为一个。谢谢。
更新:另外,我忘了提到我知道“合理化”数据库需要连接,有时还需要子查询。我通常会滥用 LEFT OUTER JOIN,但是将这些表绑定在一起以显示地址而不是执行 4 个不同的查询的最有效方法是什么?谢谢。
更新:好的,现在这可能过于规范化或不够规范化或根本没有,但是你们能告诉我你是否更喜欢这个伪模式吗?
Manufacturers
ManufacturerID (Identity)
ManufacturerName
ManufacturerStreetAddress
ManufacturerCCSZID --CCSZ (Country, City, State, Zip), needs a better name
...
ZipCodes
ZipCodeID (Identity)
ZipCode
...
States
StateID (Identity)
StateName
StateAbbreviation
...
Cities
CityID (Identity)
CityName
...
Countries
CountryID (Identity)
CountryName
CountryAbbreviation
...
CountryCityStateZipCodes
CountryCityStateZipCodeID (Identity)
CCSZCountryID
CCSZStateID
CCSZCityID
CCSZZipCodeID
要获得地址,它看起来像:
SELECT M.ManufacturerStreetAddress,
CN.CountryName,
CN.CountryAbbreviation,
S.StateName,
S.StateAbbreviation,
C.CityName,
Z.ZipCode
FROM Manufacturers M
LEFT OUTER JOIN CountryCityStateZipCodes CCSZ ON CCSZ.CountryCityStateZipCodeID = M.ManufacturerCCSZID
LEFT OUTER JOIN Countries CN ON CN.CountryID = CCSZ.CCSZCountryID
LEFT OUTER JOIN States S ON S.StateID = CCSZ.CCSZStateID
LEFT OUTER JOIN Cities C ON C.CityID = CCSZ.CCSZCityID
LEFT OUTER JOIN ZipCodes Z ON Z.ZipCodeID = CCSZ.CCSZZipCodeID
或者也许你们知道编写该查询的更好方法。但无论如何,这看起来比第一个模式更好吗?
【问题讨论】:
-
你不能那样做,邮政编码不只属于一个城市。在农村地区,他们可能在一个邮政编码中有多个小镇。当然,城市也可能有多个邮政编码。将整个地址存储在制造商地址表中。
-
嗯,据我了解,当我将包裹送到邮局时,他们并不像担心邮政编码那样担心城市/城镇。这就是为什么我想知道将城市与多个邮政编码联系起来的最佳方式,反之亦然。我相信可以做到,我确定已经做到了,我只是想知道怎么做。
-
另外,我不想存储整个地址的主要原因是因为我想提供一种简单的方法来搜索特定城市中的制造商、用户或任何对象, zipcode、state 等。使用 ID 比解析整个地址要容易得多。除非整个地址是指邮政编码、州、城市等列。
-
好的,谢谢。当我阅读你们的答案时,我记得在学校听到过“Normal Form 3”。珍惜吧。
-
邮政编码是唯一的,请将其作为邮政编码表中的主键。州缩写也是如此,因此我建议将它们用作州表中的主键。
标签: database-design cross-platform database-schema