我目前正在建模数据库模式。其中,地址被多次使用,遵循固定的结构。在我们以前的系统中,地址关系被建模为地址包含外键,例如用户的外键。
推理:这样,一个地址只能附加到一个父级。然而,从我的角度来看,这绝对是一个混乱,因为有时地址关系中最多存在八个外键,因此必须注意只有一个被填充。
将密钥放在父节点上不是更有意义吗,这样通过非零约束可以确保每个父节点都有一个地址并且地址关系是干净的?父母也很少/从不从地址侧导航到。
还是我这样做违反了任何约定?在这种情况下,清洁不比“公约”更重要吗?如果需要,还可以另外使用触发器对先前的需求进行建模吗?
是的,所以您的方法/第二种方法通常更有利和规范化,因为它会减少冗余
addresses
。但是由于这种一对一的方法,您失去了以这种方式user
拥有多个的灵活性。addresses
如果这不是逻辑模式的要求,那么您的方法更有意义。或者,为了支持两全其美的规范化和灵活性,您可以添加一个名为的表,它是两者之间的桥梁/链接表,通过将and字段存储为 all的对
userAddress
来支持多对多关系。user_id
address_id
addresses
user
简而言之:
同样对于您关于Triggers的第二个问题,它们在所有现代RDBMS中的实现方式并不完全相同(因为它们的 ANSI 兼容规范相对于 SQL 的其他功能非常少)。因此,对于一个通用的答案(因为我们不是在这个问题的上下文中讨论特定的数据库系统),如果您能够通过Trigger复制所需的行为,这取决于数据库系统。(我看到你个人使用PostgreSQL,所以我相信在这种情况下,那么使用Trigger是可能的。)
一个用户或一个公司可以有多个地址吗?通常,这是一件非常合理的事情。用户有物理地址和邮寄地址。公司有帐单地址和送货地址。如果您
address_id
在user
表格或company
表格中放置一个,您会将用户和公司限制在一个通常不是您想要的地址。用户和公司是否可以拥有相同的地址,以便更改一个地址会自动更改另一个地址?如果两者
user
都company
存在相同的行,address_id
并且用户进入并导致address
行更新,您是否真的要使公司的地址也发生变化?这可能在您的应用程序中有意义,但我认为通常您希望确保不同类型的实体引用不同的地址。作为一项规则,我通常会在 和 之间有一个映射表
user
,address
它允许一对多的关系和一个address_type
让我指定它是什么类型的地址的表。这样我就可以灵活地定义类型,例如用户的邮寄地址或公司的帐单地址或组合的用户/公司地址。您可以修改数据模型以强制执行诸如“用户只能与某些地址类型相关联”或“用户和公司不能引用相同的 address_id”之类的规则,但将这类事情作为业务规则通常是合理的应用程序管理。第一种方法
创建表地址(address_id整数主键,--与地址相关的字段);
创建表company(company_id整型主键,--企业相关字段)
创建表用户(user_id int 主键,address_id int 外键引用地址(address_id) company_id int 外键引用公司(company_id)
)
第二,如果您有多种地址类型,您可以将地址类型映射到映射表中,并将每个表中的 address_type_key 作为外键。
创建表 address_type (address_type_id 整数主键,address_type varchar(100)
-- 与地址类型相关的字段);
创建表地址(address_id整数主键,address_type_id int外键引用address_type(address_type_id),address_line_1 varchar(100),address_line_2 varchar(100),State varchar(50),country varchar(50),postalCode varchar(10)--与地址相关的字段);
创建表company(company_id整型主键,address_type_key int外键引用Address_type(address_type_id),address_key int外键引用address(address_id)--与公司相关的字段)
创建表用户( user_id int 主键,address_type_key int 外键引用 Address_type (address_type_id),address_key int 外键引用 Address(address_id) company_id int 外键引用 Company(company_id)
)