如何设计包含公司和简单客户的关系数据库

时间:2014-12-26 20:03:46

标签: mysql database-design database-schema

我必须为组织会议的公司设计数据库模式。在这些会议中可以参与私人客户或其他公司(每家公司都可以注册少数人)。目前,我需要一些关于如何将以前提到的客户保留在数据库中的建议。我想了三个方法:

  1. 将它们保存在一个名为Customers的表中,对于私人客户,将字段留空(如company_name等)。我想这是最糟糕的主意。
  2. 创建两个表:private_customercompany_customer,但似乎这些表通常会保持连接状态,因此可能会导致性能问题。
  3. customers创建一个表格,并通过customer_type之类的内容进行区分。然后创建另一个包含客户类型的表,依此类推。我想这是最好的选择。 @edit
  4. 为了更好地理解,我将写下简短摘要:

    有些公司组织会议(每次会议可能需要几天时间)。客户应通过www网站注册这些会议。作为客户,我们了解个人或公司,但会议的参与者是人(公司可以注册许多人)。公司代表可以在会议开始日期前两周保留许多座位并提供有关参与者的信息。

    我会很感激每一个提示或其他设计。如果你能告诉我关于设计数据库模式的一些资料,那将是很好的。 提前谢谢,

    马里乌什。

3 个答案:

答案 0 :(得分:2)

我首先要用更精确的语言重述要求。

  • 会议有很多参与者。
  • 会议有很多客户。
  • 客户可以是个人参与者,也可以是公司的代表。
  • 所有参与者都是客户。
  • 客户为0个或更多会议预订。
  • 类型"公司"的客户可以为多个参与者创建预订。
  • 公司类型的客户可以创建已知或未知的预订 参与者。
  • 所有参赛者必须在比赛前2周知晓 会议开始日期。

(未说明,但假设)

  • 客户可以预订多个会议。
  • 客户可以为会议提供多个预订。
  • 随着时间的推移,与会者可能属于多个客户(例如,一个人可能会参加几家公司的不同会议。)

这导致了以下几行的模式:

Conference
------------
ConferenceID (pk)
StartDate
EndDate

Client
---------
ClientID (PK)
ClientType (Company or Individual)

Reservation
------------
ClientID (FK)
ConferenceID (FK)
NumberOfAttendees 

ConferenceAttendee
-------------
AttendeeID (FK)
ClientID (FK)
ConferenceID (FK)
ConfirmationDate

Attendee
-------------
AttendeeID (PK)

然后,您可以创建只有" company"类型的客户的支票。可以为多个与会者预订,不会创建ConferenceAttendee记录,并且会议开始日期之前的确认日期不到2周。

答案 1 :(得分:1)

重要的想法是组织和个人并不完全相同,但他们并不完全不同。两者都可以有姓名,地址和电话号码,两者都可以参加会议。

对于这种事情有各种搜索术语,包括“独占弧”和“超类型/子类型”。我为PostgreSQL写了这个最小的例子,但它主要是标准的SQL。 (自动id号和触发器的语法从dbms到dbms的变化很大。)

表“派对”是超类型。表“inds”(个人)和“orgs”(组织)是子类型。每一方必须 个人或组织;即使是错误的,一方也不可能两者兼而有之。 (这是真的很重要。)

-- The "supertype". Attributes that apply to both individuals and to 
-- organizations go in this table.
--
create table parties (
    party_id serial primary key,
    party_type char(1) check (party_type in ('I', 'O')),
    party_full_name varchar(45) not null,

    -- This unique constraint lets foreign keys reference this pair
    -- of columns.
    unique (party_id, party_type)
);

-- For organizations, a "subtype" of parties. There's nothing special about
-- the column "ein". It's just an attribute that applies to organizations,
-- but doesn't apply to individuals.
--
create table orgs (
    party_id integer primary key,
    party_type CHAR(1) not null default 'O' check (party_type = 'O'),
    ein CHAR(10), -- In the USA, federal Employer Identification Number

    -- This reference to a pair of columns, together with the CHECK
    -- constraint above, guarantees that a row in this table will 
    -- reference an organization in "parties". It's impossible for 
    -- a row in this table to reference an individual.
    --
    foreign key (party_id, party_type) 
        references parties (party_id, party_type) on delete cascade
);

-- For individuals, a "subtype" of parties. There's nothing special about
-- the column "height_in" (height in inches). It's just an attribute that 
-- applies to individuals, but doesn't apply to organizations.
--
create table inds (
    party_id integer primary key,
    party_type char(1) not null default 'I' check (party_type = 'I'),
    height_in integer not null check (height_in between 24 and 108),

    -- See comments in "orgs" above.
    foreign key (party_id, party_type) 
        references parties (party_id, party_type) on delete cascade
);

客户端代码使用可更新视图,而不是基表。平台对可更新视图的支持各不相同。大多数允许在视图上触发,这是我在下面使用的。

我为下面的人写了一个视图。触发器仅处理插入。更新和删除代码非常相似。组织的查看和支持代码也类似。

create view people as
select t1.party_id, t1.party_full_name, t2.height_in
from parties t1
inner join inds t2 on (t1.party_id = t2.party_id);

create or replace function insert_into_people() 
returns trigger as
$$
begin
    insert into parties (party_full_name, party_type)
    values (new.party_full_name, 'I');
    insert into inds (party_id, height_in) values (currval('parties_party_id_seq'), new.height_in);
    return null;
end;
$$
language plpgsql;

create trigger insert_people
instead of insert on people
for each row
execute procedure insert_into_people();

在生产环境中,您可能会从几乎所有用户撤消对基表的权限,并且只允许通过视图进行访问。 (而你可能需要更多观点。)

由于个人和组织都可以参加会议,因此您的会议参与者表将引用“派对”。“party_id”。

答案 2 :(得分:0)

  

关于设计数据库模式的一些消息来源

您可以在Database Answers数据模型链接中看到许多示例模式。

NIAM方法导致了ORM2和FCO-IM。有一个free online book on FCO-IM。这些方法理解关系表具有关于应用程序的关联的parmeterized语句,并保存其元组从中生成关于应用程序的真实语句的行。