【问题标题】:How can I make this column an unique column如何使该列成为唯一列
【发布时间】:2015-09-24 02:56:50
【问题描述】:

我有很多应用程序。每个应用程序都可以分配多种语言。 每种语言都可以有多种翻译。

每个翻译都有一个Key 列,它是主键。

当 2 个应用程序使用 Key = "AdminAreaTitle" 创建翻译时,将出现重复键异常。我知道这很少会发生。但是,如果另一个应用程序具有此密钥的异常情况已经听起来很糟糕的用户体验。

我想要的是每个应用程序的翻译键,所以翻译的主键是Key,我猜是ApplicationName

您将如何扩展设计以获得该行为?

删除了错误的图片!

更新

现在这是表/关系上的 sql 视图,不再是实体框架视图。

带有代理键

更新 2

带有自然键

我必须说我更喜欢这个 ERD,因为它更易于设计和思考。代理键更令人不安。

更新 3

我创建了一个包含 3 个表的新数据库,所有自然键见截图,但我不断收到来自 sql management studio 的错误消息:

【问题讨论】:

  • 对于一对多和多对多关系,您可以创建第三个表,将两个表的主键引用为第三个表中的外键。
  • 这似乎太多了。为什么不在 Translation Table 中创建一个 FK_ApplicationName 引用 Application 表。然后这个 FK 是一个复合 PK(Key 和 ApplicationName 字段)?
  • 您在这里混合了两件事:关系的图形表示(n m,1 n)和带有主键的表描述。你不能这样做。使用两种表示中的任何一种,而不是两者的混合。如果 name 是应用程序的 PK,iso639 是语言的 PK,那么这将是 1:n 关系。但是,当您将 n:m 放在那里时,显然缺少一些东西,即 shubham agiwal 建议实现 n:m 的桥接表。
  • 是的,桥表丢失了,因为这是一个实体框架模型,再次为您的困惑感到抱歉。
  • 我也更喜欢第二张图。但是,ApplicationLanguage 和 Translation 之间没有联系,我认为这是缺乏的。并且:ISO639 必须是 Translation PK 的一部分,否则每个应用程序和密钥只能使用一种语言,我认为这是没有意义的。 (这不是应用程序+键+语言,您需要获取文本吗?如果只是应用程序和键,那么您的程序将需要知道哪个键用于英语,哪个用于西班牙语等)

标签: sql sql-server erd


【解决方案1】:

您显示的 ERD 已损坏,因为您显示的表带有它们的主键加上它们的关系 (1:n, n:m),而这些不匹配。应用程序和语言的键建议 1:n,但您的图形标记为 n:m。

您现在可能拥有的是(PK 粗体):

  • 应用程序(app_name
  • application_language(app_name、iso_lang
  • 翻译(key、iso_lang、文本)

但您希望每个应用程序定义自己的文本,因此将 app_name 添加到您的翻译表的复合 PK 中。

  • 应用程序(app_name
  • application_language(app_name、iso_lang
  • 翻译(key、app_name、iso_lang、文本)

【讨论】:

  • 抱歉,ERD 是实体框架的模型,所以它没有显示联结表 Application_Language。
  • 好的,我刚刚写了一条评论,告诉您您的 ERD 已损坏,因为图形和表格不匹配。但是,我只是注意到我没有看到 ISO 列是翻译中复合 PK 的一部分。所以我会编辑我的答案。
  • 我用新的 ERD 更新了我的问题。你怎么看?
  • 我只是认为将 Translation 表拆分为 Resource 1 和 N Localization 表是否更正确。好吧,我猜这将是一个强大的标准化......
  • 关于新的 ERD:好的,您现在使用的是技术 ID。没关系。它没有比自然键更好或更差,只是选择问题。但是,您没有正确使用此设计。 ID 应该标识表中的记录。那么ID怎么可能不是Translation的主键,而只是复合键的一部分呢?
【解决方案2】:

在 E-R 模型中,您的数据库由两个表(应用程序)和(语言)以及它们之间的关系(翻译)来描述(实体是“名词”,关系是“动词”)。

在真正的 DBMS 中,关系是一个表,其中包含正在以某种语言翻译的某个应用程序的两个主键(以及翻译本身的其他特征),使关系唯一(一个应用程序可以翻译成多种语言,一种语言可以翻译许多应用程序,但一个应用程序只能翻译一次法语)。

APPLICATION
AppName (PK)
...

LANGUAGE
LangName (PK)
...

TRANSLATE
AppName   (PK)
LangName  (PK)
...

【讨论】:

  • 这太理论化了。请您看一下实用的解决方案,以便我使用它吗?从什么时候开始关系是一张表?表是一个实体。
  • @Elisabeth - 如果表是实体,并且实体可以具有关系,您建议将这些关系存储在哪里?我可以住在很多地址,很多人也可以住在同一个地址。实体是 People 和 Addresses,然后您需要第三个表,例如“Habitation”,其中包含 PersonPK 和 AddressPK(可能还有开始和结束日期)。这样,如果有人搬家,我不需要创建新的人员或地址,只需创建新的居住记录。关系真的表。
  • 实体-关系模型是一个理论模型,需要在真实的DMBS系统中实现。正如我所说,在实际的 DBMS 中,关系也是表。您还可以在其中存储所谓的关系“属性”,例如日期。
  • 啊,我想我们这里有一个误解。您的第三张表“居住”是人员和地址的连接表吗?
  • 是的。您可以将其称为连接表。这是关系的好同义词。
【解决方案3】:

您应该存储应用程序和语言之间关系的标识,而不是将语言存储在翻译表中。这样,翻译对于该应用程序的语言将是唯一的,而不仅仅是针对该语言。

由于应用程序名称似乎是可能会改变的信息(不是在含义上,而是在描述方式上),我建议您使用数字键。

类似:

Application
  ApplicationId          int, identity, pk
  ApplicationName        nvarchar(50)

ApplicationLanguage
  ApplicationLanguageId  int, identity, pk
  ApplicationId          int
  LanguageId             int

Language
  LanguageId             int, identity, pk
  LanguageName           nvarchar(50)

Translation
  ApplicationLanguageId  int, pk
  Key                    nvarchar(20), pk
  Text                   nvarchar(max)

【讨论】:

  • Translation.Key 必须仅对 Application 而不是 Application_Language 唯一,因为资源键最终具有许多翻译/本地化,就像在 .NET String 资源编辑器中一样。你会如何改变你的结构?实际上,您只需删除 ApplicationLanguage.ApplicationLanguageId 和 Translation.ApplicationLanguageId。现在将 Application.ApplicationId (PK) 与 Translation.ApplicationId,Translation.Key 连接(两者都是 PK 但 ApplicationId 也是 FK)正确吗?
  • @Elisabeth:你错了。如果密钥对于应用程序是唯一的,则例如 MyApp/AdminAreaTitle 将只有一条记录。所以条目可以是英语或西班牙语或其他。这不是你想要的,我猜。您希望每个应用程序和语言的密钥都是唯一的,因此您可以为 MyApp/AdminAreaTitle 设置一个英文条目和一个意大利文条目,但不能有两个英文条目。因此这里显示的模型是正确的。
  • 该死的......你是对的。我总是有这个数据透视表(记住.net 字符串编辑器),其中一个键用于所有本地化。但在我的数据库中,我有许多本地化的密钥。
  • @ThorstenKettner 可以这么说,那么 Guffa 的设计是正确的,也是我想要的。
  • 是的,这很可能是您想要的。 Guffa 建议使用与我相同的数据模型,只有他使用技术 ID(Translation 表除外,您可以在其中严格并添加单独的 ID 并在 ApplicationLanguageId 和 Key 上添加唯一约束;但不那么严格也一样好),而我使用自然键。
猜你喜欢
  • 2023-03-27
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 1970-01-01
相关资源
最近更新 更多