18

所以我应该完全按照这个 ERD 描述的方式来创建这个模式 + 关系。在这里,我只显示我遇到问题的表格:

我应该一对一但我得到一对多

所以我试图做到一对一,但出于某种原因,无论我改变什么,我都会在任何有外键的表上得到一对多。

这是我对这两个表的 sql。

        CREATE TABLE lab4.factory(

            factory_id      INTEGER         UNIQUE,
            address         VARCHAR(100)    NOT NULL,
            PRIMARY KEY ( factory_id )

        );

        CREATE TABLE lab4.employee(

            employee_id     INTEGER         UNIQUE,
            employee_name   VARCHAR(100)    NOT NULL,
            factory_id      INTEGER         REFERENCES      lab4.factory(factory_id),
            PRIMARY KEY ( employee_id )

        );

在这里我得到同样的东西。我不是一对一的关系,而是一对多的关系。Invoiceline 是一个弱实体。

它必须是一对一的

这是我第二张图片的代码。

        CREATE TABLE lab4.product(

            product_id      INTEGER     PRIMARY KEY,
            product_name    INTEGER     NOT NULL

        );


        CREATE TABLE lab4.invoiceLine(

            line_number     INTEGER     NOT NULL,
            quantity        INTEGER     NOT NULL,
            curr_price      INTEGER     NOT NULL,
            inv_no          INTEGER     REFERENCES      invoice,
            product_id      INTEGER     REFERENCES      lab4.product(product_id),
            PRIMARY KEY ( inv_no, line_number )

        );

我将不胜感激任何帮助。谢谢。

4

1 回答 1

40

一对一在标准 SQL 中并不能很好地表示为一流的关系类型。与使用连接器表和两个一对多关系实现的多对多非常相似,SQL 中没有真正的“一对一”。

有几个选项:

  • 创建一个普通的外键约束(“一对多”样式),然后UNIQUE在引用的 FK 列上添加一个约束。这意味着在引用列中最多只能出现一个被引用的值,使其成为一对一的可选值。这是一种相当简单且相当宽容的方法,效果很好。

  • 使用可以模拟 1:m 的正常 FK 关系,并让您的应用程序确保它在实践中只是 1:1。我不推荐这样做,添加 FK 唯一索引只有很小的写入性能下降,它有助于确保数据有效性,发现应用程序错误,并避免混淆其他需要稍后修改架构的人。

  • 创建互惠外键 - 仅当您的数据库支持可延迟外键约束时才有可能。这对代码来说有点复杂,但允许您实现一对一的强制关系。每个实体在唯一列中都有对其他实体 PK 的外键引用。一个或两个约束必须是DEFERRABLEand either INITIALLY DEFERREDor or 与SET CONSTRAINTS调用一起使用,因为您必须推迟约束检查之一以设置循环依赖关系。这是一种相当先进的技术,对于绝大多数应用程序来说并不是必需的。

  • 如果您的数据库支持,请使用预提交触发器,这样您就可以验证当插入实体 A 时,是否也插入了一个实体 B,反之亦然,并进行相应的更新和删除检查。这可能很慢并且通常是不必要的,而且许多数据库系统不支持预提交触发器。

于 2013-02-23T05:34:24.677 回答