又一个数据库设计困境

时间:2011-11-24 10:34:16

标签: mysql database-design

我们正在使用Mysql开发Cake PHP项目。考虑我们现在拥有的这三种用户类型 - 管理员,经理和发布者(在经理下)。

目前,管理员用户可以在下拉菜单中查看发布商列表,我们需要拥有更多管理员用户,并限制他们可以查看的发布商数量,从而允许每个此类管理员查看不同的发布商组合。我们必须首先准备一个演示,然后可能会有更多的变更请求。我想对数据库设计有所了解,考虑当前的要求和一些更多的预期要求。

详情
 发布商存储在具有字段publishers的表manager_id中(发布者所在的经理)。每个出版商都有一张表中的记录。我们启用了memcaching,并且有一个memcache密钥来存储所有发布者的列表。同样,我们有管理员列表的memcache密钥,管理者和发布者的分层列表。

现在,我们需要更多管理员用户(目前只有一个),并限制他们可以查看的发布者数量。我们应该为每个这样的管理员用户提供一个限制列表,因此每个案例可以有不同的发布者组合。好像很难有10-15个这样的用户。这个部分必须在演示中,但除此之外,我们可能希望保留容易限制管理器列表的规定。因此,与发布商类似,我们应该能够为每个具有受限访问权限的管理员显示不同的管理器组合。在一些模块中,我们显示了管理者和发布者的分层列表。尚不确定如何处理该模块。我们还没有决定使用UI来编辑相关管理员用户的受限列表。目前,我们可能没有用于编辑每个管理员的受限列表的UI,因此解决方案必须很容易在后端手动编辑。

注意 - 我们将为客户提供演示。我们现在可能没有为每个管理员提供用于编辑受限列表的UI,因此解决方案必须能够在后端手动编辑内容。

我们已经考虑过这些方法 -

  1. 一个。一个新表,其中包含字段admin_idmanager_idpublisher_ids以保留关联,并为每个具有受限访问权限的管理员提供多条记录 - 每个管理员需要出现一个记录名单。 publisher_id字段将以csv格式存储该管理器下的所有发布者ID。

    湾包含字段admin_idmanager_idspublisher_ids的新表格,其中每个管理员都有一个受限制的记录。 manager_ids字段将以csv格式存储所有管理器ID,这些格式需要出现在受限列表中。所有发布者(在经理下)都将采用csv格式。

  2. 不是创建单独的表来存储限制规范,而是为发布商和经理的现有表添加新字段display_in_limited_list_of_admins。此字段将存储此发布商需要的csv管理ID列表出现。

  3. 我喜欢最后一种方法。请注意,我可能很少有10-15名管理员用户拥有受限制的权限,但是大约有数千名管理员,发布商并且仍然在增加。因此,在这种情况下,我们必须存储最少量的信息。此外,我们不必再进行任何数量的查询。我们只是在当前查询中添加where条件以获取发布者列表等。当UI准备就绪时,更新逻辑看起来很简单,只需使两个表(发布者和管理者)的display_in_limited_list_of_admins字段成立即可。到那时,我们必须手动运行这两个查询,最多

    所以,请你的意见......我可能错过的任何事情......何时/为什么有人会为此添加一个新的关联表?

2 个答案:

答案 0 :(得分:2)

也许我错过了某些东西,但它看起来像是桌子之间的n:m关系。

我是否应该为您的域名建模,我会在“管理员”和“管理员”之间创建一个关系表,在“管理员”和“发布商”之间建立另一个关系表。

admin     admin_manager       manager        manager_publisher      publisher
-----     -------------       --------       -----------------      ---------
id        admin_id            id             manager_id             id
          manager_id                         publisher_id

这样您就可以根据需要选择和分组。 例如,要选择由admin

订购的所有发布者
SELECT *
FROM admin
INNER JOIN admin_manager ON admin.id = admin_manager.admin_id
INNER JOIN manager ON admin_manager.manager_id = manager.id
INNER JOIN manager_publisher ON manager.id = manager_publisher.manager_id
INNER JOIN publisher ON manager_publisher.publisher_id = publisher.id
ORDER BY admin.id ASC, manager.id ASC

如果您只想从ID为24的管理员中选择发布商,请添加

WHERE admin.id = 24

如果你想计算出版商如何拥有一位经理:

SELECT manager.id,
       count(publisher.id) AS How_many_Publisher
FROM manager 
INNER JOIN manager_publisher ON manager.id = manager_publisher.manager_id
INNER JOIN publisher ON manager_publisher.publisher_id = publisher.id
GROUP BY manager.id
ORDER BY How_many_Publisher DESC

等等。

所有数据都已标准化,您可以根据需要添加任意数量的管理员,管理员和发布者,并且每个数据都可以与您想要的其他数据相关联。即你可以让一个发布者有一个经理,这个经理有两个管理员。

答案 1 :(得分:0)

这种事情的完整性限制有点棘手。我发现了棘手的部分。 (接近结尾。)另外,为了便于阅读和重点,我省略了ON UPDATE CASCADE和ON DELETE CASCADE。

create table admins (
  admin_id integer primary key  -- references Persons (person_id), not shown
);

insert into admins values (1);
insert into admins values (2);
insert into admins values (3);

create table managers (
  manager_id integer primary key  -- references Persons (person_id), not shown
);

insert into managers values (100);
insert into managers values (101);
insert into managers values (102);

create table publishers (
  publisher_id integer primary key,  -- references Persons (person_id), not shown
  -- A manager can manage more than one publisher.
  manager_id integer not null references managers,
  -- Not redundant. You need this unique constraint for data integrity in the 
  -- table publisher_manager_admins below.  The primary key guarantees only 
  -- one row per publisher. (Per publisher id number, that is.)
  unique (publisher_id, manager_id)
);

insert into publishers values (200,100);
insert into publishers values (201,100);
insert into publishers values (202,101);


-- Controls which publishers an admin can see.
create table viewable_publishers (
  admin_id integer not null references admins (admin_id),
  publisher_id integer not null references publishers (publisher_id),
  primary key (admin_id, publisher_id)
);

insert into viewable_publishers values (1, 200);
insert into viewable_publishers values (1, 201);
insert into viewable_publishers values (1, 202);
insert into viewable_publishers values (2, 200);
insert into viewable_publishers values (2, 201);
insert into viewable_publishers values (3, 200);


-- Controls which managers an admin can see
create table viewable_managers (
  admin_id integer not null references admins (admin_id),
  manager_id integer not null references managers (manager_id),
  primary key (admin_id, manager_id)
);

insert into viewable_managers values (1, 100);
insert into viewable_managers values (1, 101);
insert into viewable_managers values (1, 102);
insert into viewable_managers values (2, 100);


-- Allows multiple admins per publisher. It's not clear whether this is actually
-- a requirement. If you're supposed to allow only one admin per publisher,
-- create a unique constraint on (admin_id, publisher_id).
create table publisher_manager_admins (
  admin_id integer not null,
  publisher_id integer not null,
  manager_id integer not null,

  -- Tricky part--involving overlapping, compound foreign keys--follows.

  -- Allow only existing publishers and their manager. 
  foreign key (publisher_id, manager_id) 
      references publishers (publisher_id, manager_id),
  -- Allow only the publishers this admin can view.
  foreign key (admin_id, publisher_id) 
      references viewable_publishers (admin_id, publisher_id),
  -- Allow only the managers this admin can view.
  foreign key (admin_id, manager_id) 
      references viewable_managers (admin_id, manager_id) 
);

insert into publisher_manager_admins values (1, 200, 100);
insert into publisher_manager_admins values (2, 200, 100);
insert into publisher_manager_admins values (2, 201, 100);

这样的插入应该失败。

-- The table "publishers" doesn't have the row (200, 102).
insert into publisher_manager_admins values (2, 200, 102);

-- The table "viewable_managers" doesn't have the row (3, 201).
insert into publisher_manager_admins values (3, 201, 100);

-- The table "viewable_publishers" doesn't have the row (2, 202).
insert into publisher_manager_admins values (2, 202, 101);