SQL一对多表与多个一对一关系

时间:2011-08-24 22:25:50

标签: sql schema one-to-many one-to-one class-table-inheritance

我正在开发一个具有以下目标的项目:用户可以创建挑战并选择一个可选的竞争对手来参与这一挑战。挑战赛会生成每日参赛作品,并会跟踪这些参赛作品的统计数据。

基本的用户和条目实体如下所示:

CREATE TABLE users (
    id (INT),
    PRIMARY KEY (id)
);

CREATE TABLE entries (
    challengeId INT,
    userId INT,
    entryDate DATE,
    entryData VARCHAR,
    PRIMARY KEY (challengeId, userId, entryDate)
)

我遇到麻烦的是与Rival概念的挑战赛。我可以看到两种方法。

// Hard code the concept of a Challenge Owner and Rival:
CREATE TABLE challenges (
    id INT,
    name VARCHAR,
    ownerId INT,
    rivalId INT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (ownerId, name)
);

// Create Many-to-one relationship.
CREATE TABLE challenges (
    id INT,
    name VARCHAR,
    PRIMARY KEY (id),
    UNIQUE KEY (name)
)
CREATE TABLE participant (
    challengeId INT,
    userId INT,
    isOwner BIT,
    PRIMARY KEY (challengeId, userId)
)

第一种方法的问题是引用完整性很难,因为现在有两列userId(ownerId和rivalId)。为了设置外键,我必须为所有内容(owner_entries,rival_entries,owner_stats等)创建两个表。

第二种方法解决了这个问题,并且具有一些优势,例如将来允许多个竞争对手。但是,使用该方法我不能再做的一件事是在单个用户而不是整个Challenge表中强制执行Challenge名称唯一性。此外,找到挑战者所有者的任务现在变得更加棘手。

挑战表的正确方法是什么?无论如何以开发人员友好的方式设置这些表,还是我应该一直跳到类表继承并管理那里的所有者/竞争对手的概念?

2 个答案:

答案 0 :(得分:1)

我认为我设置它的方式如下(使用第二种方法):

CREATE TABLE challenges (id INT, 
                         name VARCHAR, 
                         owner_id INT, 
                         PRIMARY KEY (id),
                         UNIQUE KEY (name, owner_id))

CREATE TABLE participant (challengeId INT,
                          userId INT, 
                          PRIMARY KEY (challengeId, userId))

这样可以轻松跟踪拥有挑战,然后提取个人参与者 这样您还可以安全地使用所有者唯一标识挑战名称,并且userIdparticipant上的外键很容易。然后,“竞争对手”就是挑战所有者的所有参与者。

答案 1 :(得分:0)

我认为第一种方法是正确的。 您可以为用户提供一个表,为挑战提供一个表。

您是否知道可以像下面一样两次引用一张表?

SELECT * FROM CHALLENGES 
INNER JOIN USERS AS OWNERS ON OWNERS.ID = CHALLENGES.OWNERID
INNER JOIN USERS AS RIVALS ON RIVALS.ID = CHALLENGES.RIVALID

在这种情况下,您可以在不创建新表的情况下引用竞争对手和所有者。