一起模拟自然和法律客户的最佳方式

时间:2013-06-25 07:33:53

标签: database-design

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

方法1 : 要有这样的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,另一个为null,CustomerType显示客户类型(自然或法律)

方法2 : 要有一个包含所有字段的表:

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

为每个客户填写一些字段,其他字段为空

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

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

自然地为自然客户填充哪些字段。但如果客户是合法客户,我们会逻辑地提供数据。例如,LastName字段中的CompanyName和NationalSecurityNumber字段中的RegistrationCode以及FirstName字段为空。

方法4 : 我没有想到的任何其他方式,你可以建议

P.S。我正在MS SQL Server 2012中实现我的数据库

5 个答案:

答案 0 :(得分:7)

任何方法都有利弊,根据您的应用要求和分析,任何方法都适用。
顺便说一下,我更倾向于使用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.
    

    由于违反first normal form,你很快就会因为没有将田地分开而受苦(想想看 如果National_Security_Number)是强制值 NaturalPeople和RegistrationCode是一个可选值 LegalEntities。您无法在该字段上设置唯一密钥或强制检查。

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

  5. 您需要在Customer表上实现一个简单的搜索 高级搜索法律和自然客户。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

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

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

方法3有一个名字,目前我不知道。

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

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

答案 4 :(得分:0)

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')