数据库设计问题
我有一个有很多行为的故事。这些幕不是连续的(我不知道哪一个是第一幕,还是第二幕、第三幕等等)。
每个故事都以挑战结束。
为了表示关系数据库中的所有内容,我使用了下表:
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) 来自 Act,其中 StoryId = ?"
不起作用。)。
然后,我使用 Act.NextId 来了解此操作之后进行哪个操作或挑战。 Act.NextId
可以是行动 PK 或挑战 PK 或故事 PK。这取决于 Act.NextActionType 值。
你怎么认为?这是一个好的设计吗?
我的问题是我有挑战表,与任何其他表没有任何关系。
更新
换句话说,我需要一个系统来知道下一步该去哪里。我会有以下情况:
故事->表演->挑战->表演->挑战新故事 故事->表演->挑战->新故事
注意:行为可以不止一个。
I have a story with lots of acts. These acts are not consecutive (I don't know which is first act or second, third, and so on).
Every story ends with a challenge.
To represent all in a relational database I have used the following tables:
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
I use Story.FirstActId
to know which is the first act for story (I'm trying to say that "Select MIN(Id) from Act where StoryId = ?"
doesn't work.).
And then, I use Act.NextId
to know which act or challenge goes after this act. Act.NextId
can be an Act PK or a Challenge PK or a Story PK. This depends on Act.NextActionType
value.
What do you think? Is it a good design?
My problem is I have Challenge table without any relationship with any other table.
UPDATE
In other words, I need a system to know where to go next. I will have the following situations:
story->act->challenge->act -> new story
story->act->challente-> new story
NOTE: act can be more than one.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的表设计不是 3NF,并且有可能出现更新异常(例如,如果故事的第一幕被删除,则整个链被破坏;如果其 NextActId 被更新,则链完全改变)。另一个问题是,您必须在链上递归查找以获取故事的所有 Acts,而不是在一个查询中获取它们。
如果您希望能够在故事之间重用行为,则应该使用间接表:
如果您不需要在故事之间重用行为,那么您可以坚持使用行为表:
挑战的处理也取决于情况。
挑战也可以是一种行为吗?如果是这样,您应该将其存储在 Acts 中并拥有一个 ActsType 表:
如果挑战是一个行为,那么它作为挑战的定义是否因其在故事中的位置(最后)而被排除?如果是这样,则 ActsType 不是必需的,它只是 StoriesActMap/Act 上的 MAX 序数。
如果挑战是挑战并且永远不可能是 Act,则应将其存储在单独的表中。如果挑战可以在故事之间重用,您可以使用 StoriesChallengeMap 表;如果不能重用,则可以只使用带有
storyid
键的挑战表将其映射到故事。storyid
将是这些表上的唯一键,因为故事只有一个挑战。假设挑战始终是挑战,并且行动/挑战不能在故事之间共享,则设计如下:
现在您可以在一个查询中获取故事的所有行动和挑战。请注意,如果没有外键约束,删除故事将导致行为/挑战变得孤立。
Your table design is not in 3NF and has the potential for update anomalies (for example, if the first act of a story is deleted the entire chain is broken; if its NextActId is updated, the chain changes completely). Another problem is that you must recursively seek on the chain to get all of the Acts for a story rather than getting them in one query.
If you want to be able to reuse acts between stories, you should use an indirection table:
If you don't need to reuse acts between stories, then you can just stick with the Acts table:
The handling of challenges also depends.
Can a challenge also be an act? If so, you should store it in Acts and have an ActsType table:
If a challenge is an act, is its definition as a Challenge obviated by its position in the story (last)? If so, the ActsType is not necessary, it would just be the MAX ordinal number on StoriesActMap/Act
If a Challenge is a Challenge and can never be an Act, it should be stored in separate table. You can either have a StoriesChallengeMap table if Challenges can be reused between stories, or just the Challenge table with a
storyid
key to map it to Stories if they cannot be reused.storyid
would be a unique key on these tables since a Story only has one challenge.Assuming that a Challenge is always a Challenge and Acts/Challenges cannot be shared between stories, the design would be as follows:
Now you can get all of the Acts and the Challenge for a story in one query. Beware that a deletion of a story will orphan Acts/a Challenge if there are no foreign key constraints.
我会改变一些事情:
你会节省空间。如果 NextAct 不为空,则一个 Act 后面跟着一个 Act,
如果挑战不为空,则行动之后是挑战。
当然,条件(NextAct xor Challenge)必须始终为真。您可以通过在 Act 表中的插入中添加表约束来断言这一点。
如果您有很多类型的下一步操作(因为我们这里只有两个操作,所以很容易),您将需要以不同的方式看待问题:
“挑战只有一个行动”,
“一个法案可以有一个法案”
“ActionN has on act”
这样,您将能够找到下一个操作,如下所示:
至少有一个不会为 NULL。
I would change some things:
You will save space. An act is followed by an Act if NextAct is not null,
an Act is followed by a challenge if Challenge is not null.
Of course, the condition (NextAct xor Challenge) must always be true. You can assert this by adding a table constraint on insertions in Act table.
If you have a lot of type of next actions (since we only have two actions here, it is easy), you will need to look at the problem in a different way:
"a challenge has one Act",
"an Act can have one Act"
"ActionN has on act"
Like that, you will be able to find the next action as below:
At least one will not be NULL.
对我来说,《使徒行传》和《使徒行传》挑战似乎存储相同类型的信息,因此将它们放在不同的表中似乎有点矫枉过正。
我可能会选择......
你可以有一个标志来指示某件事是行为还是挑战。
但是,如果我理解您的描述,那么您可以通过约定来识别项目,例如将第一个项目的
Order
设置为 0 使其成为第一个 Act,并且当 Act / Challenge 是最后一个项目时该集合(即Max(Order)
)将其表示为挑战。To me, Acts & Challenges seem to store the same kind of information, hence putting them in different tables seems overkill.
I'd probably go for..
You could have a flag indicating if something is an Act or Challenge.
However, if I understand your description, then you could identify items by having a convention, e.g. setting the first item's
Order
as 0 making it the first Act, and when an Act / Challenge is the last item in the set (ieMax(Order)
) denoting it as a Challenge.在我看来,
挑战
只是行动
的一种(子)类型。考虑到Act
表包含Challenge
中所需的所有列,您只需删除表Challenge
和ActionType
即可。如果您需要知道 Act 的类型(标准与挑战),请使用ThisActionType
列而不是可能包含C,A
的NextActionType
。还要从 Story 表中删除
FirstActID
并找到一种方法来识别Act
表中的第一个/最后一个幕 - 每个幕只能属于这个故事中的一个故事model,第一个和最后一个显然很特殊。因此,完成后,它看起来会像这样
ActPosition
( F,L,A) 将用于识别第一个、最后一个或任意一个。The way I see it, the
Challenge
is simply a (sub)type ofAct
. Considering that theAct
table contains all columns needed inChallenge
, you can simply drop tablesChallenge
andActionType
. UseThisActionType
column instead of theNextActionType
which could containC,A
if you need to know what type of Act it is (standard vs challenge).Also get rid of the
FirstActID
from the Story table and find a way to identify first/last act in theAct
table -- every act can belong to only one story in this model, and first and last are obviously special.So, by the time it's done it would look something like this
ActPosition
(F,L,A) would be used to identify first, last, any.