Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database design 数据库设计问题_Database Design - Fatal编程技术网

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设置一个“导航”:故事->动作->挑战->动作->新故事。或者这个:故事->表演->挑战->新故事。行为可以不止一种。我不确定你是否理解你的问题。如果你需要更多的细节,告诉我。