【问题标题】:How to relate entities in SQL through SQL tables如何通过 SQL 表关联 SQL 中的实体
【发布时间】:2014-05-15 18:53:28
【问题描述】:

我是数据库设计的初学者,我需要为一个项目创建一个数据库。 我可以用面向对象的术语解释我想做什么,谢天谢地,数据库专家会很友好地解释我如何在数据库方面处理这个问题。

我想创建一个与位置实体(州、城市)有关系的用户(Id、Name)实体。所以在编程语言中我想要以下内容

class User {
String Name;
Int Id;
Location location; }

class Location {
String State;
String City; }

有人能解释一下我该如何处理吗?

【问题讨论】:

  • 我看到的一个解决方案是创建一个包含州和城市列的用户表,但这是处理这个问题的正确方法吗?通过这样做,如果我得到更多与用户(例如公司)之外的位置相关的元素,然后我想在位置(例如国家)上添加另一个属性,那么我将不得不去每个使用位置的表和手动添加新属性。我认为这不是很有效
  • 请通过编辑而不是 cmets 澄清。

标签: sql database database-design object-oriented-database


【解决方案1】:

这取决于您的项目要求(设计)

关系可能如下:

*用户有一个位置,位置与一个用户相关(一对一关系)

*用户拥有一个或多个位置,并且位置与一个特定用户相关(一对多关系

*用户拥有一个或多个位置,并且位置与多个用户相关(多对多关系)

【讨论】:

  • 我的关系是一个用户可能有一个位置,一个位置可以分配给一个最多多个用户,就设计方面而言。实施真的让我发疯! :)
  • 我可以看到一个包含城市和州主键的位置表,但我无法真正看到如何将它与用户表连接
  • 嗯,你想把两张桌子和一张桌子绑在一起??你知道外键吗?
【解决方案2】:

根据 cmets,您想要的是 Location 表和 User 表之间的多对一关系。这意味着一个用户将只有一个位置,但一个位置可以分配给多个用户。所以你可以看到这应该是什么样子,我已经包含了以下 DDL 脚本,或“数据定义语言”,这是所有数据库管理员使用的语言:

创建用户表:

CREATE TABLE [dbo].[User](
    [UserId] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
    [LocationId] [int] NOT NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
) ON [PRIMARY]
) ON [PRIMARY]

创建位置表:

CREATE TABLE [dbo].[Location](
    [LocationId] [int] NOT NULL,
    [City] [varbinary](50) NOT NULL,
    [State] [varchar](2) NOT NULL,
 CONSTRAINT [PK_Location] PRIMARY KEY CLUSTERED 
(
    [LocationId] ASC
) ON [PRIMARY]
) ON [PRIMARY]

现在在 2 之间创建外键 (FK)。FK 告诉数据库您要在 2 个表之间链接数据。也就是说,您不能将用户分配给位置表中不存在的位置。这是通过 Id 字段完成的。

ALTER TABLE [dbo].[User]  WITH CHECK ADD  CONSTRAINT [FK_User_Location] FOREIGN KEY([LocationId])
REFERENCES [dbo].[Location] ([LocationId])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Location]
GO

网络上有很多学习数据库设计的好资源。您需要尽早回答的一个问题是“我想让我的数据库标准化到什么程度?” Database normalization 会严重影响您的设计。

还有一件事:不要让您的应用程序对象模型决定您的数据库模型应该是什么。换句话说,您不需要在应用程序对象和数据库表之间建立一对一的关系。对于非常小的数据库来说可能是这种方式,但是使用数据库设计的最佳实践,您很快就会发现这是一种不可持续的实践。

【讨论】:

    【解决方案3】:

    一个表代表一个关系,也就是关系。因此,关系模型。即一个表包含满足某些参数化语句的行。语句的参数是表的列。

    table User on Name, Id, LocId
        // (longhand) "user identified by [Id] has name [Name] and is located in location [LocId]"
        // (shorthand) User(Name,Id,LocId)
    table Location on LocId, State and City
        // (longhand) "location [LocId] is city [City] in state [State]"
        // (shorthand) "Location(LocId,State,City)
    

    通过使用 AND、OR、AND NOT、EXISTS、IMPLIES 等组合语句获得满足其他语句的行。通过使用 JOIN、UNION、MINUS、PROJECT-OUT、

    User
        // rows satisfying User(Name,Id,LocId)
    User JOIN Location
        // rows satisfying User(Name,Id,LocId) AND Location(LocId,State,City)
    User PROJECT-OUT LocId
        // ie User PROJECT Name,Id
        // rows satisfying EXISTS LocId User(Name,Id)
    User WHERE Name='Fred'
        // rows satisfying User(Name,Id,LocId) AND Name='Fred'
    

    这就是表/语句“连接”的方式:通过参数/列名和逻辑/关系运算符。

    只有您可以决定要在表中包含哪些行,即您希望从哪些语句中组合查询。

    您用关系的某些属性回答了另一个答案(本身对关系感到困惑),但您没有说明这些关系实际上是什么,并且不足以知道表中的内容或行中的哪些语句一个查询结果满足。

    请注意,这就是您更新和查询数据库所需的全部内容。

    考虑到一些陈述和可能出现的情况,数据库只会处于某些状态。我们通过“约束”告诉 DBMS,这样它就可以防止其他状态并优化执行。例如,如果总是存在 EXISTS Name,Id User(Name,Id,LocId) IMPLIES EXISTS State,City Location(LocId,State,City) 即 USER PROJECT LocId

    您和这里的其他评论者经常遇到混淆,这些混淆被认为是对方法的错误表述,或者不幸的是方法的实际部分。例如,使用“关系”来表示对数据库中的表/关系的某些类型的约束。有人困惑地说用户和位置之间存在“a”“many:1”“关系”。这实际上意味着用户(与 Ids 为 1:1)和位置(与 LocIds 为 1:1)之间的表/关系 User PROJECT Id,LocId 即 EXISTS Name User(Name,Id,LocId) 具有多:1的属性,即在某些数据库状态下,许多用户可以位于同一位置。然后这与从用户到位置的包含约束或 FK 进一步混淆。然后人们就模糊地认为这样的东西“连接”了表:但它们约束表(即数据库)并且与查询无关。

    阅读有关 NIAM 或 FCO-IM 或对象角色建模的信息,它们将告诉您如何清晰地思考设计。 (Halpin 的书告诉您如何从 ORM2 映射到 ER 和其他,而不会因常见的误解而扭曲。)

    【讨论】:

      猜你喜欢
      • 2012-08-02
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 2013-05-26
      • 2019-12-02
      • 2015-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多