【问题标题】:Adding foreign key constraint to associative entity向关联实体添加外键约束
【发布时间】:2015-03-26 20:26:23
【问题描述】:

我有 3 张桌子:

1) SERVICE_REQUESTS(父)

CREATE TABLE SERVICE_REQUESTS(
service_id           NUMBER (7)    NOT NULL,
serial_number        NUMBER (10)   NOT NULL,
service_date         DATE          NOT NULL,
service_description  VARCHAR(50)   NOT NULL,
hourly_rate          NUMBER(5,2)   NOT NULL,
customer_id          NUMBER  (5)   NOT NULL,
employee_id          NUMBER  (3)   NOT NULL,

CONSTRAINT service_request_pk PRIMARY KEY(service_id, serial_number));


2)SERVICE_PARTS(解决M:M关系的关联实体)

CREATE TABLE SERVICE_PARTS(
service_id           NUMBER  (7)   NOT NULL,
part_id              NUMBER (10)   NOT NULL,
quantity             NUMBER  (4)   NOT NULL,
unit_cost            NUMBER(7,2)   NOT NULL,

CONSTRAINT service_part_pk PRIMARY KEY(service_id, part_id));


3) 部分(父)

CREATE TABLE PARTS(
part_id              NUMBER (10)   NOT NULL,
part_description     VARCHAR(50)   NOT NULL,
cost                  NUMBER(7,2)   NOT NULL,
quantity_on_hand     NUMBER  (5)   NOT NULL,

CONSTRAINT part_pk PRIMARY KEY(part_id));


我使用以下语句创建了一个从 SERVICE_PARTSPARTS 的外键约束:

ALTER TABLE service_parts
  ADD CONSTRAINT service_parts_part_id_fk
    FOREIGN KEY (part_id)
      REFERENCES parts(part_id);

现在我正在尝试使用以下语句创建从 SERVICE_PARTSSERVICE_REQUESTS 的外键约束:

ALTER TABLE service_parts
  ADD CONSTRAINT service_parts_service_id_fk
    FOREIGN KEY (service_id)
      REFERENCES service_requests(service_id);

但我收到以下错误:ORA-02270: no matching unique or primary key for this column-list。为什么它允许为part_id而不是service_id添加约束?

我附上了我的 ER 图以进行视觉澄清:

【问题讨论】:

  • 您问题中的图表和文字冲突。该图有一个SERVICE_REQUEST 表,主键为service_id,但文本描述的表名称为SERVICE_REQUESTS,主键为(service_id, serial_number)。那么哪个是正确的?请更新图表或文字。
  • 嗨,鲍勃,感谢您提出这个问题。我们在课堂上使用的程序隐藏了识别主键。 SERVICE_REQUEST 表右侧的>|---- 中的| 表示EQUIPMENT 表中的主键也被用作SERVICE_REQUEST 表中的主键/外键。与SERVICE_PART 表类似,它有2 个>|----|< 来自SERVICE_REQUEST 实体和PART 实体。这意味着SERVICE_PART 表中的主数据库由SERVICE_REQUESTPART 实体标识。

标签: oracle foreign-keys many-to-many constraints composite-key


【解决方案1】:

如果service_requests 表的主键是service_id, serial_number,则您的 M:M 映射表需要包含主键的两个元素。主键的定义意味着您可以有许多行具有相同的service_id 但不同的serial_number 值。如果您的映射表不包含键的两个元素,您将无法确定service_requests 中的哪个特定行映射到service_parts 中的任何特定行。

您的映射表定义需要是

CREATE TABLE SERVICE_PARTS(
service_id           NUMBER  (7)   NOT NULL,
serial_number        NUMBER (10)   NOT NULL,
part_id              NUMBER (10)   NOT NULL,
quantity             NUMBER  (4)   NOT NULL,
unit_cost            NUMBER(7,2)   NOT NULL,

CONSTRAINT service_part_pk PRIMARY KEY(service_id, serial_number, part_id));

然后是你的外键

ALTER TABLE service_parts
  ADD CONSTRAINT service_parts_service_id_fk
    FOREIGN KEY (service_id, serial_number)
      REFERENCES service_requests(service_id, serial_number);

或者,如果我们认为您的映射表是正确的,这意味着service_idservice_requests 的键,那么service_requests 的定义将是

CREATE TABLE SERVICE_REQUESTS(
service_id           NUMBER (7)    NOT NULL,
serial_number        NUMBER (10)   NOT NULL,
service_date         DATE          NOT NULL,
service_description  VARCHAR(50)   NOT NULL,
hourly_rate          NUMBER(5,2)   NOT NULL,
customer_id          NUMBER  (5)   NOT NULL,
employee_id          NUMBER  (3)   NOT NULL,

CONSTRAINT service_request_pk PRIMARY KEY(service_id));

那么你的映射表和你的外键定义将是正确的。

【讨论】:

  • 嗨贾斯汀,再次感谢您的帮助。这次我附上了一张图片,以帮助更好地解释这一点。我假设我必须从EQUIPMENT 表中为我的SERVICE_REQUESTS 建立一个识别关系。我这样做有错吗?
  • 我没有看到equipment 表(我看不到您上传的图像,可能被我的防火墙阻止了)。
  • EQUIPMENT 表具有以下属性:serial_number, brand, model, equipment_type,然后表中有 4 个子类型。所以serial_number 是主键,我已经从SERVICE_REQUESTS 表中引用了它。 ER Diagram Link
【解决方案2】:

你在表SERVICE_REQUESTS中的主键:

CONSTRAINT service_request_pk PRIMARY KEY(service_id, serial_number)

这样的主键不能保证你的service_id 值是唯一的。因此,您不能仅从另一个表中引用该字段,因为无法确定您将引用哪条记录。您在一个表中的主键和另一个表中的外键必须完全相同。

【讨论】:

  • 抱歉,我的serial_number 是设备表的外键,它必须是唯一的。让我附上我的 ER 图来帮助更好地说明这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 2010-12-30
  • 2014-06-01
  • 1970-01-01
相关资源
最近更新 更多