2011-04-27 136 views
0

我有很多行爲的故事。這些行爲不是連續的(我不知道哪一個是第一個行爲或第二個,第三個等等)。數據庫設計問題

每個故事都以挑戰結束。

,以表示我已經使用了下面的表格關係數據庫中的所有:

Story 
--------------------------------------- 
Id    | PK 
Name   | String 
FirstActId  | FK to ACT table 

Act 
--------------------------------------- 
Id    | PK 
StoryId   | FK to STORY table 
Name   | String 
Description  | Very long string 
NextActionType | FK to ACTIONTYPE table 
NextId   | Its value depends on NextActionType 

ActionType 
--------------------------------------- 
Id    | PK 
Name   | Values= 'Act', 'Challenge', 'Story'. 

Challenge 
--------------------------------------- 
Id    | PK 
Name   | String 
Description  | Very long string 
NextActionType | FK to ACTIONTYPE table 
NextId   | Its value depends on NextActionType 

我用Story.FirstActId知道這是故事的第一幕(我想說,"Select MIN(Id) from Act where StoryId = ?"不起作用)。

然後,我用Act.NextId知道該行爲之後應該採取哪種行爲或挑戰。 Act.NextId可以是一個行動PK或一個挑戰PK或一個故事PK。這取決於Act.NextActionType的值。

您認爲如何?這是一個好的設計嗎?

我的問題是我有挑戰表與任何其他表沒有任何關係。

UPDATE

換句話說,我需要一個系統,要知道接下來要去哪裏。我將有以下幾種情況:

故事 - > ACT->挑戰 - >行爲 - >新的故事 故事 - > ACT-> challente->新的故事

注意:行爲可以比更一。

+0

如果您不知道哪種行爲是第一次,第二次等,您如何存儲FirstActId? – 2011-04-27 13:25:26

+0

我知道哪個行爲是我添加故事和行爲時的第一行爲。我試圖說:「從Story中選擇MIN(Id)where StoryId =?」不起作用。 – VansFannel 2011-04-27 13:27:19

回答

0

我看到它的方式,Challenge只是一個(子)類型的Act。考慮到Act表包含Challenge中所需的全部列,您可以簡單地刪除表ChallengeActionType。如果您需要知道它是什麼類型的行爲(標準vs挑戰),請使用ThisActionType列而不是NextActionType,其中可能包含C,A

還可以獲得從故事表格擺脫FirstActID,並找到一種方法來識別Act表第一/最後一幕 - 每一個行爲只能屬於一個故事,在這個模型中,並且第一個和最後顯然是特別的。

所以,在時間它完成它會是這個樣子

enter image description here

ActPosition(F,L,A)將首先用於識別,最後,任何。

+0

我忘了說nextActionType也可以是一個故事。我用更好的細節更新了我的問題。抱歉。 – VansFannel 2011-04-27 13:28:53

+0

@VansFannel,在這種情況下,'NextActID'只會指向不同'StoryID'的第一幕。 – 2011-04-27 13:39:59

0

我會改變一些事情:

Act 
--------------------------------------- 
... 
NextAct   | FK to Act table, can be NULL 
Challenge  | FK to Challenge table, can be NULL 

No need of ActionType 

您將節省空間。如果NextAct不爲空,則該行爲後跟一個行爲 如果挑戰不爲空,則行爲跟隨挑戰。

當然,條件(NextAct異或挑戰)必須始終爲真。您可以通過在Act表格中添加一個表格約束來插入。

如果你有很多類型的下一步行動的(因爲我們只有兩個動作在這裏,很容易),你需要看問題以不同的方式: 「的質疑有一分法」, 「法案能有一個法」 「ActionN對行動」

這樣,你就可以找到,因爲下面的下一個動作:

SELECT 
    challenge_id, 
    act_id, 
    ... 
FROM 
    Act 
LEFT OUTER JOIN 
    Act NextAct ON Act.next_act_id = NextAct.act_id 
... 
LEFT OUTER JOIN 
    Challenge ON Act.challenge_id = Challenge_id 

至少有一個會不會是NULL。

+0

我忘了說nextActionType也可以是一個故事。我用更好的細節更新了我的問題。抱歉。 – VansFannel 2011-04-27 13:29:19

+0

它不會改變任何東西,必須創建一個具有關係兒童 - >父母而不是父 - >子女的樹/圖結構。 – 2011-04-27 13:39:28

0

對我來說,使徒行傳&挑戰似乎存儲了相同類型的信息,因此把它們放在不同的表格中似乎有點矯枉過正。

我可能會去..

Story 
--------------------------------------- 
Id    | PK 
Name   | String 
FirstActId  | FK to ACT table 

Items (Acts or Challenges) 
--------------------------------------- 
Id    | PK 
StoryId   | FK to STORY table 
Name   | String 
Description  | Very long string 
Order   | Int - which position this Act/Challenge should go in 

你可以有一個標誌,指示,如果事情是一種行爲或挑戰。但是,如果我瞭解你的描述,那麼你可以通過約定來識別項目,例如,將第一項Order設置爲0使其成爲第一項法案,並且當動作/挑戰是該組中的最後一項(即Max(Order))時,將其表示爲挑戰。

1

您的表格設計不在3NF中,並有更新異常的可能性(例如,如果故事的第一個動作被刪除,則整個鏈條被破壞;如果其NextActId更新,鏈條完全更改)。另一個問題是,你必須遞歸地在鏈上尋找所有的行爲來獲得一個故事,而不是讓他們在一個查詢中。

如果你希望能夠故事之間重複使用的行爲,你應該使用一個間接表:

StoriesActsMap 
-------------- 
storyid 
actid 
ordinal_number 

如果你不需要重用故事之間的行爲,那麼你可以堅持使用行爲表:

Act 
    ------------- 
    actid 
    actDescription, etc. 
    ordinal_number 
    storyid 

挑戰的處理也取決於。

一個挑戰也是一種行爲嗎?如果是這樣,你應該把它存放在行爲和有ActsType表:

Act 
    -------------- 
    actid 
    acttypeid 
    ...see rest of Act above 

    ActsType 
    -------------- 
    acttypeid 
    acttype (Act, Challenge) 

如果一個挑戰是一種行爲,是其定義爲挑戰由它的故事(最後)位置消除?如果是這樣,ActsType不是必需的,它只是StoriesActMap/Act上的MAX序號。如果一個挑戰是一個挑戰並且永遠不可能是一個行爲,它應該存儲在單獨的表格中。如果挑戰可以在故事之間重複使用,或者只有挑戰表與storyid鍵,如果它們不能重複使用,則將其映射到故事,您可以擁有StoriesChallengeMap表。因爲故事只有一個挑戰,所以storyid將成爲這些表格上的唯一鍵。

假設一個挑戰始終是一個挑戰和行爲/挑戰無法故事之間共享,設計將是如下:

Story 
---------- 
storyid 
other info 

Act 
---------- 
actid 
storyid 
actorder (ordinal number of acts, (actorder, storyid) is a prime) 
other info 

Challenge 
---------- 
chid 
storyid 
other info 

現在你可以得到所有的行爲和挑戰的一個故事在一個查詢中。注意,如果沒有外鍵約束,刪除故事將孤兒徒/挑戰。

+0

在閱讀您的問題更新之後,我的設計無法處理故事後的故事。故事總是會跟着挑戰嗎?或者,故事可以在任何時候成爲下一個動作? – 2011-04-27 13:59:32

+0

我正在使用nextActionType和nextId來設置一個'導航'我可以有:story-> act-> challenge-> act-> new story。或者這一個:故事 - >行動 - >挑戰 - >新故事。行爲可能不止一個。我不確定是否理解你的問題。如果你需要更多的細節,告訴我。 – VansFannel 2011-04-27 15:47:43