2014-02-14 34 views
2

得到了一個項目,我工作的一個小型關係問題,我試着用搜索引擎的答案,但不知道用什麼詞彙來找到我的答案洛爾MySQL的關係圈

的要解決的問題:

用戶可以有許多照片,其中一張照片可以是個人資料照片,但只有一張。

因此,例如:

CREATE TABLE user (
    ID Int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    username varchar(25) NOT NULL 
); 
CREATE TABLE photo (
    ID Int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    user_ID Int NOT NULL, 
    imgpath varchar(260) NOT NULL, 
    FOREIGN KEY (user_ID) REFERENCES user (ID) ON UPDATE CASCADE 
); 
CREATE table userprofphoto (
    user_ID Int NOT NULL, 
    photo_ID Int NOT NULL, 
    FOREIGN KEY (photo_ID) REFERENCES photo (ID) ON UPDATE CASCADE, 
    FOREIGN KEY (user_ID) REFERENCES user (ID) ON UPDATE CASCADE 
); 

所以一個查詢來獲取用戶的個人資料照片將是:

SELECT imgpath FROM photo WHERE photo_ID=(SELECT photo_ID FROM userprofphoto WHERE user_ID=:userid LIMIT 1) 

這工作,但它會創建一個關係圈。我應該/可以解決這個問題嗎?

我沒想到從userprofphoto表中刪除了user_ID,但隨後這將增加查詢長度:

SELECT imgpath FROM photo 
LEFT JOIN userprofphoto ON userprofphoto.photo_ID=photo.ID 
WHERE photo.user_ID=:user_id 

讚賞任何幫助:d

+0

你不必在你的設計中的任何環雖然。 –

+0

它確實...因爲userprofphoto有FK user.ID和FK photo.ID,並且照片有FK user.ID –

+0

這是2個路徑(從userprofphoto到user),而不是一個循環。 –

回答

0

您可以從userprofphoto刪除photo_ID並添加表photo上的一列profile_photo的值將爲1/0在您的條件下添加profile_photo=1

當用戶選擇個人資料照片只需更新profile_photo = 1,在這種情況下,你必須做兩個更新首次更新set profile_photo=0 where profile_photo=1秒更新將被設置set profile_photo=1 where ID=[PHPTO_ID]

1

你的第一個查詢是沒有意義的,因爲imgpath是隻在您的設計中使用photos。 (順便說一下,我通常更喜歡用表名而不是單數形式,這有助於避免與保留字的衝突。)

您的設計的一個問題是表userprofphoto對它沒有任何限制。所以用戶可以擁有多個個人資料照片。通過在表中字段user_ID上添加唯一約束或唯一索引,可以很容易地解決這個問題。

除了這個小調整,你的設計很好。還有兩種方法。

一個是在photo表中有一個標誌,用於指定照片用於配置文件。這在MySQL中很難維護。其他數據庫具有使這更容易的功能。

但是,最好的解決方案可能是完全刪除userprofphoto表,只需在user中添加一列即可。這自動執行那裏只有一個配置文件照片的約束。當然,如果你以後決定取消這個限制,那麼你需要重新引入userprofphoto表。

您可能還想要一個約束,即用戶實際擁有該個人資料照片。這需要在MySQL中實現觸發器。您可以在添加和修改個人資料照片的邏輯中處理此操作。

通過這種結構,您的查詢將是:

SELECT imgpath 
FROM users u join 
    photos p 
    ON u.profile_photo_ID = p.photo_ID; 
WHERE u.user_ID = :user_id; 
+0

是的......注意到我的錯誤查詢大聲笑......改變了它:D另外,歡呼獨特的索引想法 –

+0

@戈登,如果我們添加一個'profile_photo_id'列到'用戶',我們將在外鍵引用中有一個循環。而且由於MySQL沒有實現延遲約束,所以很難管理。 –

+0

@ypercube。 。 。您可以在之後添加一個單獨的「alter table」語句(http://www.sqlfiddle.com/#!2/e091d)。 –

1

要強制你提要求,我會用下面的設計:

  • 添加一個唯一的(或主鍵)約束下因此每個用戶只有一個配置文件照片
  • 將配置文件表中的兩個外鍵約束更改爲一個。使用您當前的設計,您可以結束附加到不同用戶的用戶的個人資料照片。

(我還沒有使用ID的名字,但user_IDphoto_ID等隨處可見):

CREATE TABLE user (
    user_ID Int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    username varchar(25) NOT NULL 
); 

CREATE TABLE photo (
    photo_ID Int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    user_ID Int NOT NULL, 
    imgpath varchar(260) NOT NULL, 
    UNIQUE (user_ID, photo_ID),   -- this is is needed for the FK below 
    FOREIGN KEY (user_ID) 
     REFERENCES user (user_ID) 
     ON UPDATE CASCADE 
); 

CREATE table userprofphoto (
    user_ID Int NOT NULL, 
    photo_ID Int NOT NULL, 
    PRIMARY KEY (user_ID),   -- only one profile photo per user 
    FOREIGN KEY (user_ID, photo_ID) 
     REFERENCES photo (user_ID, photo_ID) 
     ON UPDATE CASCADE 
);