您很难找到它,因为它不是真正的(在被广泛采用和鼓励的意义上)数据库设计模式。
远离这样的模式。虽然 ORM 使将数据库表映射到类型更容易,但表不是类型,反之亦然。虽然尚不清楚您描述的模型应该做什么,但您不应该将列用作多个表的假外键(当我说“假”时,我的意思是您正在存储一个简单的标识符值对应另一个表的主键,但实际上不能将该列定义为外键)。
为您的数据库建模以表示数据,为您的对象建模以表示流程,并使用您的 ORM 和中间层进行转换;不要尝试将数据库推送到您的代码中,也不要尝试将您的代码推送到数据库中。
根据评论进行编辑
您正在混合使用数据库和 OO 术语;虽然我不熟悉您用于定义该函数的语法,但我假设它是 User 类型上的一个实例函数,称为 getLocation,它不接受任何参数并返回一个 Location 对象。数据库不支持实例(或任何基于类型)函数的概念;关系数据库可以具有用户定义的函数,但这些是简单的过程函数,它们接受参数并返回值或结果集。除了您可以在函数体中使用它们之外,它们不以任何方式对应于特定的表或字段。
话虽如此,这里有两个问题需要回答:如何按照您的要求做,以及什么可能是更好的解决方案。
对于您所问的,听起来您有一种超类型-子类型关系,这是一种标准的数据库设计模式。在这种情况下,您有一个表示父级的超类型表:
Location
---------------
LocationID (PK)
...other common attributes
(请注意,为了简单起见,我在这里使用LocationID;如果可能的话,您应该有更具体和合乎逻辑的属性来定义主键)
那么你有一个或多个定义子类型的表:
Address
-----------
LocationID (PK, FK to Location)
...address-specific attributes
Country
-----------
LocationID (PK, FK to Location)
...country-specific attributes
如果Location 的特定实例只能是其中一个子类型,那么您应该向父表 (Location) 添加一个鉴别器值,指示它对应于哪个子类型。您可以使用CHECK 约束来确保给定行的此字段中只有有效值。
不过,最后,听起来您可能会更好地使用混合方法。从我所见,您基本上代表了两种不同类型的位置:
- 基于坐标的位置 (L&L)
- 基于市政/邮政/等的位置(国家/地区、城市、地址),其中每一个都只是前一个的更具体的版本
鉴于此,一个简单的模型将如下所示:
Location
------------
LocationID (PK)
LocationType (non-nullable) ('C' for coordinate, 'P' for postal)
LocationCoordinate
------------------
LocationID (PK; FK to Location)
Latitude (non-nullable)
Longitude (non-nullable)
LocationPostal
------------------
LocationID (PK, FK to Location)
Country (non-nullable)
City (nullable)
Address (nullable)
现在唯一剩下的问题是我们有可以为空的列。如果你想让你的查询保持简单,但从人们那里得到(有道理的!)关于保留可空列的批评,那么你可以保持原样。如果您想使用大多数人认为设计更好的数据库,您可以将我们的两个可空列移至 6NF。这样做还有一个很好的副作用,就是让我们可以更好地控制这些字段的填充方式,而无需做任何额外的事情。
我们的两个可空字段是City 和Address。我将假设没有City 的Address 是无稽之谈。在这种情况下,我们从LocationPostal 表中删除这两个属性并创建另外两个表:
LocationPostalCity
------------------
LocationID (PK; FK to LocationPostal)
City (non-nullable)
LocationPostalCityAddress
-------------------------
LocationID (PK; FK to LocationPostalCity)
Address (non-nullable)