【问题标题】:"no matching unique or primary key for this column-list" Error in SQL“此列列表没有匹配的唯一键或主键”SQL 中的错误
【发布时间】:2022-01-10 14:50:03
【问题描述】:

我在 SQL 中创建了一些表,但在我必须设计以下表时卡住了:

如您所见,如果没有客户收据表,则无法创建房间详细信息和服务详细信息表,因为它们包含 Receipt_no 作为主键。

同样,如果不先创建两个明细表,就不可能创建没有 Room_charges 和 Service_charges 属性的 Customer Receipt 表。

因此,我首先创建了一个客户收据表,但对 Room_ChargesService_charges 没有 FK 约束,然后我创建了 Services Details 和 Room Details 表。

后来,使用 ALTER 命令我尝试在客户收据表上添加 FK 约束,但它给了我这个错误

ORA-02270: 此列列表没有匹配的唯一键或主键

现在,在 StackOverflow 上对其进行了一些研究后,可能存在批准的答案中提到的三种可能情况 (@Oracle (ORA-02270) : no matching unique or primary key for this column-list error)

我认为我的案例是第 3 号,因为我已确保前两个案例得到实施。

谁能帮我解决?

我附上 SQL 代码作为参考:

CREATE TABLE Customer_Receipt 
(
     Receipt_no VARCHAR2(12) PRIMARY KEY,
     Booking_no NUMBER NOT NULL,
     Total_charges NUMBER(12,2),

     CONSTRAINT bookingnocustrec 
         FOREIGN KEY(Booking_no) REFERENCES Room_booking (Booking_no)
);
 
CREATE TABLE Services_Details 
(
    Receipt_no VARCHAR2(12) NOT NULL,
    Service_offered VARCHAR2(8) NOT NULL,
    Service_charges NUMBER(12,2),

    PRIMARY KEY(Receipt_no, Service_offered),
    CONSTRAINT recno 
        FOREIGN KEY(Receipt_no) REFERENCES Customer_receipt (Receipt_no)
);

ALTER TABLE Services_Details 
    MODIFY Service_charges NOT NULL; 
 
CREATE TABLE Room_Details 
(
    Receipt_no VARCHAR2(12) NOT NULL,
    Category_name VARCHAR2(9) NOT NULL,
    Days_stayed INT,
    Room_charges NUMBER(12,2),

    PRIMARY KEY(Receipt_no, Category_name),
    CONSTRAINT recno1 
        FOREIGN KEY(Receipt_no) REFERENCES Customer_receipt (Receipt_no),
    CONSTRAINT catname1 
        FOREIGN KEY(Category_name) REFERENCES Room_category (Category_name)
);

ALTER TABLE Customer_receipt
    ADD Room_charges NUMBER(12,2) NOT NULL;

ALTER TABLE Customer_receipt
    ADD CONSTRAINT FK_RC
        FOREIGN KEY (Room_charges) REFERENCES Room_Details (Room_charges);

【问题讨论】:

  • 错误很明显:表room_details中的列room_charges不是主键或唯一的。它可能真的不是独一无二的。该表的主键是room_id,“charge”可能是指每晚的费用或类似的费用,对于几个不同的房间可能相同。如何解决这个问题不太明显;您与我们分享的唯一信息是不符合要求的代码。仅凭这一点,我们无法推断出需要什么。
  • 我运行了 alter 命令使 room_charges NOT NULL .. 即使在那之后它给了我这个错误。请告诉我我应该与您分享更多信息吗?
  • “not null”与“unique”有什么关系?
  • @mathguy 抱歉,我回答错误。实际上,我认为 FK 应该始终为 NOT NULL 并且将其与唯一约束混合在一起。我接到你了。这是否意味着我必须使 room_charges 唯一才能在其上添加 FK 约束?然后我猜我的 ERD 设计有错误。你能告诉我为什么必须在 FK 上添加唯一约束吗?
  • 不在 FK 上 - 在 PK 上。 FK 不必是唯一的或非空的。引用的列在其表中不需要是 PK (尽管经常是),但它必须是唯一的。同样,我无法告诉您如何修复您的设计,因为您实际上并没有告诉我们您需要什么;但几乎可以肯定,键(唯一/主键和外键)不应该在 room_charges 列上。

标签: sql oracle


【解决方案1】:

作为框架挑战。

谁能帮我解决?

是的,当数据已存储在Service_DetailsRoom_Details 表。

如果您将相同的数据存储在两个位置,那么您很可能会遇到这两个位置之间的数据不一致的情况;只需将每条数据存储在一个位置,这样您的数据库中就有一个单一的事实来源。

CREATE TABLE Customer_Receipt 
(
     Receipt_no VARCHAR2(12)
                CONSTRAINT custreceipt__recno__pk PRIMARY KEY,
     Booking_no CONSTRAINT custreceipt__bookingno__fk REFERENCES Room_booking
                NOT NULL
);

CREATE TABLE Services_Details 
(
  Receipt_no      CONSTRAINT servicedetails__recno__fk REFERENCES Customer_receipt
                  NOT NULL,
  Service_offered VARCHAR2(8)
                  NOT NULL,
  Service_charges NUMBER(12,2),

  CONSTRAINT servicedetails__recno_servoff__pk PRIMARY KEY(Receipt_no, Service_offered)
);

CREATE TABLE Room_Details 
(
    Receipt_no    CONSTRAINT roomdetails__recno__fk REFERENCES Customer_receipt
                  NOT NULL,
    Category_name CONSTRAINT roomdetails__catname__fk REFERENCES Room_category
                  NOT NULL,
    Days_stayed   INT,
    Room_charges  NUMBER(12,2),

    CONSTRAINT roomdetails__recno_catname__pk PRIMARY KEY(Receipt_no, Category_name)
);

如果您想显示Total_ChargesService_ChargesRoom_Charges,请使用JOIN 并从相关表中获取数据。比如:

SELECT cr.*,
       COALESCE(s.service_charges, 0) AS service_charges,
       COALESCE(r.room_charges, 0) AS room_charges,
       COALESCE(s.service_charges, 0) + COALESCE(r.room_charges, 0)
         AS total_charges
FROM   customer_receipt cr
       LEFT OUTER JOIN (
         SELECT receipt_no,
                SUM(service_charges) AS service_charges
         FROM   services_details
         GROUP BY receipt_no
       ) s
       ON cr.receipt_no = s.receipt_no
       LEFT OUTER JOIN (
         SELECT receipt_no,
                SUM(days_stayed * room_charges) AS room_charges
         FROM   room_details
         GROUP BY receipt_no
       ) r
       ON cr.receipt_no = r.receipt_no;

或者创建一个视图(或物化视图)。

【讨论】:

  • 感谢您的回答。一切看起来都很好。就一件事。首先,是否有从 CUSTOMER_RECEIPT 表中排除 Total_charges 属性的原因?其次,如果我添加此属性,则它等于'service_charges'+'room_charges*days_stayed'。你能告诉我如何执行吗?我在想触发器,但写不出来。
  • @Shaheer 仍然不违反 3NF。如果total_charges 是根据其他表中的其他数据计算得出的,则计算它而不是尝试使用触发器存储值。我已将答案更新为乘以 days_stayed
猜你喜欢
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
相关资源
最近更新 更多