Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在数据库中表示继承?_Sql Server_Inheritance_Database Design_Class Table Inheritance - Fatal编程技术网

Sql server 如何在数据库中表示继承?

Sql server 如何在数据库中表示继承?,sql-server,inheritance,database-design,class-table-inheritance,Sql Server,Inheritance,Database Design,Class Table Inheritance,我正在考虑如何在SQLServer数据库中表示复杂的结构 考虑一个应用程序,它需要存储一系列对象的详细信息,这些对象共享一些属性,但有许多其他属性并不常见。例如,商业保险包可能包括同一保单记录中的责任险、汽车险、财产险和赔偿险 在C#等中实现这一点很简单,因为您可以创建一个包含节集合的策略,其中节根据各种类型的保险单的需要进行继承。然而,关系数据库似乎不容易做到这一点 我可以看到有两个主要的选择: 创建一个策略表,然后创建一个节表,其中包含所有可能的变量所需的字段,其中大多数变量为空 创建一个保

我正在考虑如何在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);