【问题标题】:Best way to model Natural and Legal Customers all together将自然客户和合法客户一起建模的最佳方式
【发布时间】:2013-06-25 07:33:53
【问题描述】:

我想设计我的项目的数据模型,但我在“客户”部分遇到了问题,因为我有两种类型的客户:自然人和法人实体 哪种方式最好:

方法一: 有 3 个这样的表:

    Customers:
    ID int not null (PK)
    CustomerType bit not null
    NaturalPersonID int (FK)
    LegalPersonID int (FK)

    NaturalPeople:
    ID int not null (PK)
    FirstName nvarchar(50) not null
    LastName nvarchar(50) not null
    NationalSecurityNumber char(10) not null
    ...

    LegalEntities:
    ID int not null (PK)
    CompanyName nvarchar(100) not null
    RegistrationNumber char(20) not null
    ...

填写 NaturalPersonID 或 LegalPersonID 中的一个,另一个为空,CustomerType 显示客户的类型(自然或法律)

方法二: 拥有一个包含所有字段的表:

    ID int not null (PK)
    CustomerType bit not null
    FirstName nvarchar(50)
    LastName nvarchar(50)
    NationalSecurityNumber char(10)
    CompanyName nvarchar(100)
    RegistrationNumber char(20)
    ...

每个客户的某些字段已填写,其他字段为空

方法三: 要有一个包含一些字段的表:

    ID int not null (PK)
    CustomerType bit not null
    FirstName nvarchar(50)
    LastName nvarchar(100)
    NationalSecurityNumber varchar(20)
    ...

为自然客户自然填充的字段。但如果客户是合法客户,我们会按逻辑放置数据。例如,LastName 字段中的 CompanyName 和 NationalSecurityNumber 字段中的 RegistrationCode 并且 FirstName 字段为空。

方法四: 我没有想到的任何其他方式,您可以提出建议

附:我正在 MS SQL Server 2012 中实现我的数据库

【问题讨论】:

标签: database-design


【解决方案1】:

任何方法都有优点和缺点,根据您的应用程序要求和分析,它们中的任何一种都适用。
顺便说一句,我更喜欢使用 Method 1 并考虑一些因素:

  1. Customer 表将是 NaturalPeople 的基表和 LegalEntities,客户的主键就是主键 的另外两个。
  2. 客户表将包含:
    其他两个人的共享信息,如客户编号、客户类型....
    搜索客户全名(标准名称)等关键字段,以便您可以对其设置索引
  3. 避免将一个字段用于两个不同的业务价值,例如:

    The fields are filled for the natural customers naturally. 
    But if the customer is a Legal one, we put data logically. For example 
    CompanyName in the LastName field and RegistrationCode in
    the NationalSecurityNumber field and the FirstName field is null.
    

    如果不将字段分开,您迟早会受到影响,因为违规g first normal form(认为 如果 National_Security_Number ) 是强制值 NaturalPeople 和 RegistrationCode 是一个可选值 法律实体。您不能在字段上设置唯一键或强制检查。

  4. 其他实体(如帐户、标志、地址...)将拥有 仅引用 Customer 表。

  5. 您需要在 Customer 表上实现一个简单的搜索,然后 对合法客户和自然客户进行高级搜索。

【讨论】:

  • 如果一个实体可以是 LegalEntities 和 NaturalPeople ?也就是说,可以从 LegalEntities 或 NaturalPeople 派生的实体
  • 考虑到我使用的是方法1
【解决方案2】:

在这种情况下,我通常会做一个表 Customer,它有一个 PK 和一个鉴别器列 CustomerType,还有两个详细表,一个用于 Natural,一个用于 Legal,但这些附加表的主键与Customers 表的 PK(类似于您的方法一,但没有两个子类型表的单独键)。这样查询更简单,您可以在 master 和 detail 之间强制执行 1:0 约束,没有代理键并且数据被规范化。

【讨论】:

    【解决方案3】:

    简单地说:不要忘记自然人和法人实体之间存在潜在的关系,自然人属于或代表法人实体。我会毫不犹豫地将 LegalEntityID FK 添加到 NaturalPeople 表中。

    而且,为了简单起见,当它指向“NaturalPeople”表时,我不会将外键字段命名为“NaturalPersonID”。称它为 NaturalPeopleID,它会让事情变得更清晰。 “LegalPersonID”字段也是如此。您甚至可以将对象/表的名称限制为“人”和“实体”,或“人”和“机构”(这是为了避免实体对象/表与关系数据库中的实体概念之间出现任何混淆)。

    【讨论】:

      【解决方案4】:

      方法 1 是一种称为 的设计模式。

      方法 2 是一种称为 的设计模式。

      您可以通过访问标签并打开信息标签来阅读这些内容。

      方法 3 有个名字,我现在不知道。

      在你的情况下,我会选择方法 1。

      在方法 1 中,您已经非常严格地遵循了该模式。我建议您考虑的一件事是共享主键。类表继承和共享主键可以很好地协同工作。

      【讨论】:

        【解决方案5】:
        create table party_type (
          id serial primary key,
          description text not null unique
        );
        
        insert into party_type ('description') values
        ('Organization'),
        ('Individual'),
        ('Automated Agent');
        
        create table party (
          id serial primary key,
          party_type_id int not null references party_type(id),
          organization_name text null,
          last_name text null,
          first_name text null,
        );
        
        insert into party (party_type_id, organization_name) values (1, 'Acme, Inc');
        insert into party (party_type_id, last_name, first_name) values (2 'Doe', 'John');
        
        create table role_type (
          id serial primary key,
          description text not null unique
        );
        
        insert into role_type ('description') values
        ('Customer'),
        
        create table party_role (
          party_id int not null references party(id),
          role_type_id int not null references party_role_type(id),
          primary key (party_id, role_type_id)
        );
        
        /* add both parties as customers: */
        insert into party_role values (1, 1);
        insert into party_role values (2, 1);
        
        create table identifier_type (
          id serial primary key,
          description text not null unique
        );
        
        insert into identifier_type ('description') values
        ('Social Security Number'),
        ('Registration Number');
        
        create table party_identifier (
          party_id int not null references party(id),
          identifier_type_id int not null references identifier_type(id),
          id_number text not null,
          primary key (party_id, identifier_type_id)
        );
        
        insert into party_identifier values
        (1, 2, 'some company reg number'),
        (2, 1, 'some ssn')
        

        【讨论】:

          猜你喜欢
          • 2010-10-13
          • 1970-01-01
          • 2011-04-05
          • 1970-01-01
          • 1970-01-01
          • 2010-09-16
          • 2017-09-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多