我必须为组织会议的公司设计数据库模式。在这些会议中可以参与私人客户或其他公司(每家公司都可以注册少数人)。目前,我需要一些关于如何将以前提到的客户保留在数据库中的建议。我想了三个方法:
Customers
的表中,对于私人客户,将字段留空(如company_name等)。我想这是最糟糕的主意。private_customer
和company_customer
,但似乎这些表通常会保持连接状态,因此可能会导致性能问题。customers
创建一个表格,并通过customer_type
之类的内容进行区分。然后创建另一个包含客户类型的表,依此类推。我想这是最好的选择。
@edit 为了更好地理解,我将写下简短摘要:
有些公司组织会议(每次会议可能需要几天时间)。客户应通过www网站注册这些会议。作为客户,我们了解个人或公司,但会议的参与者是人(公司可以注册许多人)。公司代表可以在会议开始日期前两周保留许多座位并提供有关参与者的信息。
我会很感激每一个提示或其他设计。如果你能告诉我关于设计数据库模式的一些资料,那将是很好的。 提前谢谢,
马里乌什。
答案 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语句,并保存其元组从中生成关于应用程序的真实语句的行。