0

我正在设计一个数据库来跟踪用户及其与不同组织的关系。一个用户可以属于多个组织,一个组织可以有多个用户。这部分很容易通过多对多关系解决。然而,事情变得更加模糊的是,用户也可以是一个或多个组织的管理员,并且用户需要能够记录每个组织花费的时间。

似乎有很多方法可以解决这个问题。这是我到目前为止的表结构,如果您认为有更好的方法,我想听听您的意见。

CREATE TABLE `organization` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
    PRIMARY KEY (`id`)
);

CREATE TABLE `user` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `first_name` VARCHAR(50) NOT NULL COLLATE 'utf8_unicode_ci',
    `last_name` VARCHAR(50) NOT NULL COLLATE 'utf8_unicode_ci',
    `email` VARCHAR(50) NOT NULL COLLATE 'utf8_unicode_ci',
    `password` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
    PRIMARY KEY (`id`),
    UNIQUE INDEX `email` (`email`)
);

CREATE TABLE `time_log` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `user_organization_id` INT(11) NOT NULL,
    `date` DATE NOT NULL,
    `time` TINYINT(4) NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `user_organization_id` (`user_organization_id`),
    CONSTRAINT `fk_time_log_user_organization` FOREIGN KEY (`user_organization_id`) REFERENCES `user_organization` (`id`)
);

CREATE TABLE `user_organization` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `user_id` INT(11) NOT NULL,
    `organization_id` INT(11) NOT NULL,
    `admin` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`, `user_id`, `organization_id`, `admin`) USING BTREE,
    INDEX `user_id` (`user_id`),
    INDEX `organization_id` (`organization_id`),
    CONSTRAINT `fk_user_organization_organization` FOREIGN KEY (`organization_id`) REFERENCES `organization` (`id`),
    CONSTRAINT `fk_user_organization_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
);

我选择使用表id上的字段,user_organization因为它使创建表的外键time_log更容易。但是,我也可以将user_id, 和也organization_id放入其中time_log table

4

2 回答 2

0
CREATE TABLE `user_organization` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,  -- remove
    `user_id` INT(11) NOT NULL,            -- don't you want INT UNSIGNED?
    `organization_id` INT(11) NOT NULL,
    `admin` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`, `user_id`, `organization_id`, `admin`) USING BTREE,  -- Bad!
    INDEX `user_id` (`user_id`),  -- see below
    INDEX `organization_id` (`organization_id`),
    CONSTRAINT `fk_user_organization_organization` FOREIGN KEY (`organization_id`) REFERENCES `organization` (`id`),
    CONSTRAINT `fk_user_organization_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
);

-->

CREATE TABLE `user_organization` (
    `user_id` INT(11) NOT NULL,
    `organization_id` INT(11) NOT NULL,
    `admin` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`user_id`, `organization_id`)     -- PK, and lookup from user
    INDEX `organization_id` (`organization_id`, user_id),  -- lookup the other way
    CONSTRAINT `fk_user_organization_organization` FOREIGN KEY (`organization_id`) REFERENCES `organization` (`id`),
    CONSTRAINT `fk_user_organization_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB;        -- don't let it default to MyISAM
于 2015-09-06T19:14:49.463 回答
0

在交集表中标记管理员不是一个好主意。如果没有标记特定组织的用户或同一组织标记了多个用户,会发生什么情况?一种好方法是有一个单独的 OrgAdmins 表。

create table OrgAdmins(
    UserID   int  not null,
    OrgID    int  not null,
    Assigned date not null,
    constraint PK_OrgAdmins primary key( OrgID ),
    constraint FK_OrgAdmins_OrgUser foreign key( UserID, OrgID )
        references user_organization( user_id, organization_id )
);

将 OrgID 设为关键字段会限制每个组织的一个条目。使 UserID、OrgID 引用交叉表可确保将管理员正确定义为组织的用户。

类似的布局可以用于时间日志表。但是那个时间是组织每个用户的总时间,还是用户在组织“花费时间”的每个时间段都有一个条目?如果是前者,那么 (UserID, OrgID) 对将是主键和外键。如果是后者,这是一个“事件”表,它通常没有主键——每个引用可能出现多个条目,并通过事件的日期和时间来区分。

于 2015-09-08T17:22:15.013 回答