Sql server 如何在数据库中表示继承?
我正在考虑如何在SQLServer数据库中表示复杂的结构 考虑一个应用程序,它需要存储一系列对象的详细信息,这些对象共享一些属性,但有许多其他属性并不常见。例如,商业保险包可能包括同一保单记录中的责任险、汽车险、财产险和赔偿险 在C#等中实现这一点很简单,因为您可以创建一个包含节集合的策略,其中节根据各种类型的保险单的需要进行继承。然而,关系数据库似乎不容易做到这一点 我可以看到有两个主要的选择:Sql server 如何在数据库中表示继承?,sql-server,inheritance,database-design,class-table-inheritance,Sql Server,Inheritance,Database Design,Class Table Inheritance,我正在考虑如何在SQLServer数据库中表示复杂的结构 考虑一个应用程序,它需要存储一系列对象的详细信息,这些对象共享一些属性,但有许多其他属性并不常见。例如,商业保险包可能包括同一保单记录中的责任险、汽车险、财产险和赔偿险 在C#等中实现这一点很简单,因为您可以创建一个包含节集合的策略,其中节根据各种类型的保险单的需要进行继承。然而,关系数据库似乎不容易做到这一点 我可以看到有两个主要的选择: 创建一个策略表,然后创建一个节表,其中包含所有可能的变量所需的字段,其中大多数变量为空 创建一个保
此场景的最佳实践是什么?第三个选项是创建一个“策略”表,然后创建一个“SectionsMain”表,该表存储了跨节类型通用的所有字段。然后为每种类型的节创建其他表,这些表只包含不通用的字段 决定哪一个是最好的主要取决于您有多少字段以及您希望如何编写SQL。他们都会工作。如果您只有几个字段,那么我可能会选择#1。对于“很多”字段,我倾向于使用#2或#3。我倾向于使用方法#1(一个统一的节表),以便高效地检索整个策略及其所有节(我认为您的系统将做很多) 此外,我不知道您使用的是哪个版本的SQL Server,但在2008+中,当一列中的许多值都为空时,可以帮助优化性能
最终,您必须决定策略部分的“相似性”。除非它们有实质性的不同,否则我认为一个更规范化的解决方案可能会比它的价值更麻烦。。。但只有你才能打那个电话。:) 根据提供的信息,我将对数据库进行建模,使其具有以下内容: 政策
- 策略ID(主键)
- 责任ID(主键)
- 策略ID(外键)
- 属性ID(主键)
- 策略ID(外键)
节
表,除了策略_id
,还会有一个节_类型_代码
无论哪种方式,这都将允许您支持每个策略的可选部分
我不理解您对这种方法有什么不满意的地方——这是您在保持引用完整性和不复制数据的同时存储数据的方式。这个术语是“标准化的”
因为SQL是基于集合的,所以它与过程性/面向对象编程概念相当陌生&需要代码从一个领域转换到另一个领域。ORMs经常被考虑,但它们在高容量、复杂的系统中不能很好地工作。在他的书中描述了三种继承模型,当时提出了SQL反模式的解决方案。这是一个简要概述:
单表继承(也称为每个层次结构的表继承):
在第一个选项中使用单个表可能是最简单的设计。正如您所提到的,许多特定于子类型的属性必须在这些属性不适用的行上指定一个NULL
值。使用此模型,您将有一个策略表,其外观如下所示:
+------+---------------------+----------+----------------+------------------+
| id | date_issued | type | vehicle_reg_no | property_address |
+------+---------------------+----------+----------------+------------------+
| 1 | 2010-08-20 12:00:00 | MOTOR | 01-A-04004 | NULL |
| 2 | 2010-08-20 13:00:00 | MOTOR | 02-B-01010 | NULL |
| 3 | 2010-08-20 14:00:00 | PROPERTY | NULL | Oxford Street |
| 4 | 2010-08-20 15:00:00 | MOTOR | 03-C-02020 | NULL |
+------+---------------------+----------+----------------+------------------+
\------ COMMON FIELDS -------/ \----- SUBTYPE SPECIFIC FIELDS -----/
保持设计简单是一个优点,但这种方法的主要问题如下:
- 在添加新的子类型时,必须修改表以适应描述这些新对象的属性。当您有许多子类型时,或者如果您计划定期添加子类型,这很快就会成为问题
- 由于没有元数据来定义哪些属性属于哪些子类型,数据库将无法强制执行哪些属性适用,哪些属性不适用
- 您也不能对应该是强制的子类型的属性强制执行
。您必须在应用程序中处理此问题,这通常并不理想notnull
--// Table: policies_motor
+------+---------------------+----------------+
| id | date_issued | vehicle_reg_no |
+------+---------------------+----------------+
| 1 | 2010-08-20 12:00:00 | 01-A-04004 |
| 2 | 2010-08-20 13:00:00 | 02-B-01010 |
| 3 | 2010-08-20 15:00:00 | 03-C-02020 |
+------+---------------------+----------------+
--// Table: policies_property
+------+---------------------+------------------+
| id | date_issued | property_address |
+------+---------------------+------------------+
| 1 | 2010-08-20 14:00:00 | Oxford Street |
+------+---------------------+------------------+
CREATE TABLE person (
id int ,
name varchar(20),
CONSTRAINT pessoa_pkey PRIMARY KEY (id)
);
CREATE TABLE natural_person (
social_security_number varchar(11),
CONSTRAINT pessoaf_pkey PRIMARY KEY (id)
) INHERITS (person);
CREATE TABLE juridical_person (
tin_number varchar(14),
CONSTRAINT pessoaj_pkey PRIMARY KEY (id)
) INHERITS (person);
该设计将基本上解决单表法确定的问题:
- 强制属性现在可以通过
强制执行NOT NULL
- 添加新的子类型需要添加新表,而不是向现有表添加列
- 也没有为特定子类型设置不适当属性的风险,例如属性策略的
字段vehicle\u reg\u no
- 在单表方法中,不需要使用
属性。类型现在由元数据定义:表名类型
- 公共属性与特定于子类型的属性混合在一起,没有简单的方法来识别它们。数据库也不会知道
- 定义表时,必须为每个子类型表重复公共属性。那绝对不是
- 无论子类型如何,都很难搜索所有策略,并且需要大量的
联合
CREATE TABLE policies ( policy_id int, date_issued datetime, -- // other common attributes ... ); CREATE TABLE policy_motor ( policy_id int, vehicle_reg_no varchar(20), -- // other attributes specific to motor insurance ... FOREIGN KEY (policy_id) REFERENCES policies (policy_id) ); CREATE TABLE policy_property ( policy_id int, property_address varchar(20), -- // other attributes specific to property insurance ... FOREIGN KEY (policy_id) REFERENCES policies (policy_id) );
CREATE TABLE person ( id int , name varchar(20), CONSTRAINT pessoa_pkey PRIMARY KEY (id) ); CREATE TABLE natural_person ( social_security_number varchar(11), CONSTRAINT pessoaf_pkey PRIMARY KEY (id) ) INHERITS (person); CREATE TABLE juridical_person ( tin_number varchar(14), CONSTRAINT pessoaj_pkey PRIMARY KEY (id) ) INHERITS (person);