2011-08-24 131 views
1

我正在使用以下目标来处理项目:用户可以创建一个挑战并选择一个可选的对手来参与此挑战。挑战生成每日条目并将跟踪这些数据。SQL一对多表与多个一对一关系

基本用户和入境实体是这样的:

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

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

我遇到的麻烦的部分是一块面临的挑战与对手的概念。我可以看到两种方法。

// 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) 
) 

与第一种方法的问题是,参照完整性是艰难的,因为现在有地方的userIds居住(OWNERID和rivalId)两列。我必须为所有东西(owner_entries,rival_entries,owner_stats等)创建两个表以设置外键。

第二种方法解决了这个问题,并具有一些优点,如允许将来有多个对手。然而,我无法再用这种方法做的一件事就是在单个用户中强制挑战名称唯一性,而不是整个挑战表。此外,寻找挑战者的任务现在更加棘手。

什么是挑战表的正确方法?有没有办法以开发人员友好的方式设置这些表格,还是应该跳到Class Table Inheritance并在那里管理Owner/Rivals的概念?

+0

您使用的数据库是?我们一直在SQL Server中对同一个pk字段执行多个外键。这消除了您对第一种方法的反对意见。第二种方法可能仍然会更好,如果您需要超过2人参与挑战。 – HLGEM

+0

他的真正反对意见并不是为同一个pk字段设置多个fks(他正在这样做),而是将一个fk字段设置为多个pks。我不认为这在一般情况下是可能的,除了是相当有问题的... –

+0

我经常在SQL Server中使用触发器来强制执行特殊的唯一性要求,例如, “用户名”只需在活动帐户中唯一。 – HABO

回答

0

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

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

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

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

+0

让用户很容易,这是我关心的入口和可能的统计。以我描述的Entry模型为例,如何在强制引用完整性的情况下跟踪单个表中的用户条目,以便只有属于挑战的用户才能输入条目?看起来好像我需要拥有challengeId和ownerId的OwnerEntries表,然后是带有challengeId和rivalId的RivalEntries表。 – Cowlby

+0

在这种情况下,您可以添加引用挑战的统计表,具体取决于所需的数据。或者,您可以将审计模式应用于您的表格:检出[this](http://stackoverflow.com/questions/3823/suggestions-for-implementing-audit-tables-in-sql-server)后。 –

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)) 

这使得拥有挑战容易跟踪,但提取出个人的参与者。
这也可以让你安全地对所有者独有的挑战名称,并且在participant中的userId的外键很容易。 '对手'然后是所有参与者而不是挑战所有者。