Database design 数据库设计问题
我有一个有很多表演的故事。这些动作不是连续的,我不知道是第一幕还是第二幕、第三幕等等 每一个故事都以挑战告终 为了表示关系数据库中的所有数据,我使用了以下表格:Database design 数据库设计问题,database-design,Database Design,我有一个有很多表演的故事。这些动作不是连续的,我不知道是第一幕还是第二幕、第三幕等等 每一个故事都以挑战告终 为了表示关系数据库中的所有数据,我使用了以下表格: Story --------------------------------------- Id | PK Name | String FirstActId | FK to ACT table Act --------------------------------------
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来知道哪个是Story的第一个动作,我想说的是,从actwherestoryid=?不起作用
然后,我使用Act.NextId来知道在这个动作之后是哪一个动作或挑战。Act.NextId可以是Act PK、挑战PK或故事PK。这取决于Act.NextActionType值
你觉得怎么样?这个设计好吗
我的问题是我的挑战表与其他表没有任何关系
更新
换句话说,我需要一个系统来知道下一步要去哪里。我会有以下情况:
故事->表演->挑战->表演->新故事
故事->表演->查伦特->新故事
注意:act可以不止一个。在我看来,挑战只是act的一个子类型。考虑到Act表包含质询中所需的所有列,您可以简单地删除质询表和ActionType表。如果您需要知道什么类型的动作是标准动作还是挑战动作,请使用ThisActionType列,而不是可能包含C、A的NextActionType
另外,从故事表中去掉FirstActID,并找到一种方法来识别act表中的第一个/最后一个动作——在这个模型中,每个动作只能属于一个故事,而且第一个和最后一个显然是特殊的
所以,当它完成的时候,它会看起来像这样
ActPosition F,L,A将用于识别第一个、最后一个或任意位置 我会改变一些事情:
Act
---------------------------------------
...
NextAct | FK to Act table, can be NULL
Challenge | FK to Challenge table, can be NULL
No need of ActionType
这样可以节省空间。如果NextAct不为空,则act后面跟着act,
如果质询不为空,则Act后面跟着质询
当然,NextAct xor挑战的条件必须始终为真。您可以通过在Act表中的插入上添加表约束来断言这一点
如果您有很多类型的后续操作,因为我们这里只有两个操作,这很简单,您需要以不同的方式来看待问题:
挑战只有一个动作,
一个动作可以有一个动作
Action已经开始行动了
这样,您将能够找到下一个操作,如下所示:
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
至少有一个不会为空。对我来说,Acts&Challenges似乎存储了相同类型的信息,因此将它们放在不同的表中似乎有些过分 我可能会选择
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
你可以有一个标志,表明某件事是一个行为还是一个挑战
但是,如果我理解您的描述,那么您可以通过约定来识别项目,例如,将第一个项目的顺序设置为0,使其成为第一个动作,当一个动作/挑战是集合中的最后一项时,即MaxOrder将其表示为挑战。您的表格设计不在3NF中,并且有可能出现更新异常。例如,如果故事的第一个动作被删除,则整个链条将断开;如果更新了其NextActId,则链将完全更改。另一个问题是,您必须递归地在链上搜索,以获取一个故事的所有行为,而不是在一个查询中获取它们 如果希望能够在故事之间重用动作,则应使用间接表:
StoriesActsMap
--------------
storyid
actid
ordinal_number
如果您不需要在故事之间重复使用acts,那么您可以继续使用acts表:
Act
-------------
actid
actDescription, etc.
ordinal_number
storyid
挑战的处理也取决于
挑战也可以是一种行为吗?如果是,则应将其存储在Acts中,并具有ActsType表:
Act
--------------
actid
acttypeid
...see rest of Act above
ActsType
--------------
acttypeid
acttype (Act, Challenge)
如果挑战是一种行为,那么它在故事中的位置是否可以消除它作为挑战的定义?如果是这样,则不需要ActsType,它只是StoriesActMap/Act上的最大序号
如果一个质询是一个质询,并且永远不能是一个动作,那么它应该存储在单独的表中。如果可以在故事之间重用挑战,则可以使用StoriesChallengeMap表;如果无法重用挑战,则可以使用带有storyid键的挑战表将其映射到故事。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
现在,您可以在一个查询中获得一个故事的所有动作和挑战。请注意,如果没有外键约束,删除故事将导致孤立行为/挑战。如果您不知道哪个行为是第一个、第二个等。如何存储FirstActId?我在添加故事和行为时知道哪个行为是第一个。我想说的是,从Act where StoryId=?不行。我忘了说nextActionType也可以是一个故事。我用更详细的信息更新了我的问题。抱歉。@VansFannel,在这种情况下,NextActID只会指向不同StoryID的第一个动作。我忘了说nextActionType也可以是一个story。我用更详细的信息更新了我的问题。对不起,我
t不会改变任何东西,必须创建一个树/图形结构,其中包含关系Children->Parent和not Parent->Children。在阅读了您对问题的更新后,我的设计不会处理下面的故事。故事总是伴随着挑战吗?或者一个故事在任何时候都可以成为下一个动作吗?我正在使用nextActionType和nextId设置一个“导航”:故事->动作->挑战->动作->新故事。或者这个:故事->表演->挑战->新故事。行为可以不止一种。我不确定你是否理解你的问题。如果你需要更多的细节,告诉我。