2

将“Arnold Schwarzenegger”和“Hasta la vista baby”插入到以下空 SQL 表中,我的陈述是什么?

这个问题的标题原本是“如何将第一条记录插入到具有双向关联和自动生成整数PK的SQL表中?” 但我不确定我的措辞是否正确......基本上,我有两张桌子ActorsCatchPhrases.

Actors好像:

  ActorId                  int             NOT NULL  PK (autogenerated by db)
  FavoriteCatchPhraseId    int             NOT NULL  FK
  Name                     varchar(200)    NOT NULL

CatchPhrases好像:

  CatchPhraseId            int             NOT NULL  PK (autogenerated by db)
  ActorId                  int             NOT NULL  FK
  PhraseText               varchar(500)    NOT NULL

因此,Actor 可以有多个流行语,但必须至少有一个。流行语与演员相关联。目前这两个表中都没有数据。

4

3 回答 3

5

我会以不同的方式对其进行建模以避免双向关系(这很难做到)。只需在 CatchPhrases 表中添加一列 (IsFavorite)。在代码中使用约束或业务规则将标记为每个参与者最喜欢的流行语的数量限制为一个。

演员:

ActorId                  int             NOT NULL  PK (autogenerated by db)
Name                     varchar(200)    NOT NULL

口头禅:

CatchPhraseId            int             NOT NULL  PK (autogenerated by db)
ActorId                  int             NOT NULL  FK
PhraseText               varchar(500)    NOT NULL
IsFavorite               bit             NOT NULL

确保您在 ActorId 上有一个 CatchPhrases 表的索引,以便您可以快速找到演员的流行语。

或者,使用连接表——这将允许多个参与者拥有相同的流行语。

演员:

ActorId                  int             NOT NULL PK (autogenerated by db)
Name                     varchar(200)    NOT NULL

演员口号

ActorId                  int             NOT NULL PK (FK to Actors)
CatchPhraseId            int             NOT NULL PK (FK to CatchPhrases)
IsFavorite               bit             NOT NULL

口头禅

PhraseId                 int             NOT NULL PK (autogenerated by db)  
PhraseText               varchar(500)    NOT NULL
于 2011-03-05T17:35:35.570 回答
2

规则,即父记录必须至少有一个子记录,不能通过声明性引用完整性来强制执行。

“Favorite”是单数,因此FavoriteCatchPhrase 可以只是Actor 实体的一个属性,即Actors 表中的一列。您可以存储短语的文本。但是,如果您想强制执行规则,即最喜欢的流行语必须来自一组真实的流行语,这些短语已经过审查并被认为是真正“吸引人”的,而不仅仅是一些不那么令人难忘的说法,那么您将有一个 CatchPhrases 表,并且您可以让 Actor.FavoriteCatchPhrase 存储短语 id 并将 CatchPhrases 表作为外键引用,但多个演员可以使用相同的标语,除非您在 Actor.FavoriteCatchPhrase 上放置唯一索引。

于 2011-03-05T19:53:48.887 回答
1

我认为您可以通过使用“脏读”(未提交读)在事务中执行此操作。

但即使可能,它也不是很好。

正如@tvanfosson 建议的那样,最干净的方法是关闭 CatchPhrases 表的 ActorId 列上的 FK。

首先创建一个虚拟 CatchPhrases (set identity insert on) 行,如:

0 - 0 - '没有最喜欢的标语',0

然后,当您要插入 Actors 行时,可以使用默认值:

(身份) - 0 - '阿诺德施瓦辛格'

然后将变量设置为 Actors 插入将生成的 @@identity 值

然后是口头禅:

(身份)-(变量)-'Hasta la vista baby'

然后将变量设置为 CatchPhrases 插入将生成的 @@identity 值,并使用它来更新演员行中的标语 id。

……呸,你确定这个设计是对的吗?

编辑

好吧,如果我们可以改变设计......

从关系来看,Actor 可以有很多 Catchphrases,Catchphrases 可以有很多 Actor。所以有一个多对多的设计——通常使用链接实体进行重构(MSDN 称之为联结表):

Actors   
  |
-----
| | |
ActorsCatchphrases
| | |
-----
  |
Catchphrases
  • Actors 有 Actor Name 和 Actor 详细信息(没有引用流行语)
  • ActorsCatchphrases 具有 ActorId 和 CatchphraseId 以及关于它是否是该演员的最爱的布尔值
  • 标语有标语的详细信息(不涉及演员)
于 2011-03-05T18:01:54.167 回答