Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Thực thi ràng buộc duy nhất hỗn hợp phụ thuộc vào giá trị cột mẹ

Tôi tin rằng đây là một trong những trường hợp hiếm hoi mà việc sử dụng các khóa thay thế (id của auto_increment) thay vì các khóa tự nhiên đã khiến bạn lạc lối. Hãy xem xét các định nghĩa bảng của bạn sẽ trông như thế nào nếu bạn sử dụng các khóa tự nhiên để thay thế:

CREATE TABLE showing
(
    name            VARCHAR(45) NOT NULL,   -- globally unique
    PRIMARY KEY (name)
)

CREATE TABLE reservation
(
    showing_name    VARCHAR(45) NOT NULL,
    name            VARCHAR(45) NOT NULL,   -- only unique within showing_name
    PRIMARY KEY (name, showing_name),
    FOREIGN KEY (showing_name) REFERENCES showing(name)
)

CREATE TABLE reservation_seat
(
    showing_name    VARCHAR(45) NOT NULL,
    reservation_name VARCHAR(45) NOT NULL,
    seat_row        VARCHAR(45) NOT NULL,
    seat_column     VARCHAR(45) NOT NULL,
    confirmed       TINYINT,
    PRIMARY KEY (showing_name, reservation_name, seat_row, seat_column),
    FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
    FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column)
)

Giờ đây, bạn có thể thêm chỗ ngồi đã đặt trước của mình mỗi khi hiển thị ràng buộc làm Khóa thay thế trên chỗ đặt chỗ:

CREATE TABLE reservation_seat
(
    showing_name    VARCHAR(45) NOT NULL,
    reservation_name VARCHAR(45) NOT NULL,
    seat_row        VARCHAR(45) NOT NULL,
    seat_column     VARCHAR(45) NOT NULL,
    confirmed       TINYINT,
    PRIMARY KEY (showing_name, reservation_name, seat_row, seat_column),
    FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
    FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column),
    CONSTRAINT UC_seat_showing_reserved UNIQUE(showing_name, seat_row, seat_column)
)

Tuy nhiên, điều này cho thấy rõ ràng rằng khóa chính là không cần thiết vì nó chỉ là phiên bản yếu hơn của ràng buộc mà chúng tôi đã thêm vào, vì vậy chúng ta nên thay thế nó bằng ràng buộc mới của mình.

CREATE TABLE reservation_seat
(
    showing_name    VARCHAR(45) NOT NULL,
    reservation_name VARCHAR(45) NOT NULL,
    seat_row        VARCHAR(45) NOT NULL,
    seat_column     VARCHAR(45) NOT NULL,
    confirmed       TINYINT,
    PRIMARY KEY (showing_name, seat_row, seat_column),
    FOREIGN KEY (showing_name, reservation_name) REFERENCES reservation(showing_name, name),
    FOREIGN KEY (seat_row, seat_column) REFERENCES seat(row, column)
)

Hiện tại, chúng tôi có thể lo lắng rằng booking_seat của chúng tôi có thể tham chiếu đến một đặt chỗ với một display_id khác với chính bản thân Booking_seat, nhưng đó không phải là vấn đề đối với các khóa tự nhiên vì tham chiếu khóa ngoại đầu tiên ngăn cản điều đó.

Bây giờ, tất cả những gì chúng ta cần làm là dịch lại khóa này thành các khóa thay thế:

CREATE TABLE reservation_seat
(
    id              INT  NOT NULL  AUTO_INCREMENT,
    showing_id      INT  NOT NULL,
    reservation_id  INT  NOT NULL,
    seat_id         INT  NOT NULL,
    confirmed       TINYINT,
    PRIMARY KEY (id),
    FOREIGN KEY (showing_id, reservation_id) REFERENCES reservation(showing_id, id),
    FOREIGN KEY (seat_id) REFERENCES seat(id),
    CONSTRAINT UC_seat_showing_reserved UNIQUE(showing_id, seat_id)
)

Bởi vì chúng tôi đang đặt chỗ_chỉ (id) làm khóa chính, chúng tôi phải thay đổi định nghĩa PK được đặt tên trở lại thành một ràng buộc duy nhất. So với định nghĩa booking_seat ban đầu của bạn, chúng tôi kết thúc với việc thêm shows_id, nhưng với định nghĩa khóa ngoại đầu tiên mạnh hơn được sửa đổi, giờ đây chúng tôi đảm bảo rằng cả booking_seat đều là duy nhất trong một chương trình và booking_seat không được có shows_id khác với định nghĩa dành riêng cho cha mẹ của nó.

(Lưu ý:bạn có thể sẽ phải trích dẫn tên cột 'hàng' và 'cột' trong mã SQL ở trên)

Lưu ý bổ sung: DBMS khác nhau về điều này (và tôi không chắc về MySql trong trường hợp này), nhưng nhiều người sẽ yêu cầu quan hệ Khoá ngoại phải có Khoá chính hoặc Ràng buộc duy nhất tương ứng trên bảng đích (được tham chiếu). Điều này có nghĩa là bạn sẽ phải thay đổi đặt chỗ bảng có ràng buộc mới như:

CONSTRAINT UC_showing_reserved UNIQUE(showing_id, id)

để phù hợp với định nghĩa FK mới trên chỗ_đặt_giá mà tôi đã đề xuất ở trên:

FOREIGN KEY (showing_id, reservation_id) REFERENCES reservation(showing_id, id),

Về mặt kỹ thuật, đây sẽ là một ràng buộc thừa vì nó là phiên bản yếu hơn của khóa chính trên bảng đặt chỗ, nhưng trong trường hợp này, SQL có thể vẫn yêu cầu nó triển khai FK.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thuộc tính đối tượng PHP có dấu ngoặc trong đó

  2. nhận mysql_insert_id () trong khi sử dụng CẬP NHẬT KHÓA DUPLICATE với PHP

  3. nhận được db:SQLSTATE [HY000] [2002] Lỗi từ chối kết nối trên Mac với MAMP

  4. cách tốt nhất để gọi hai máy chủ cơ sở dữ liệu

  5. Truy vấn MySQL - Kết hợp dữ liệu dựa trên hai yếu tố, sau đó tùy chỉnh cách dữ liệu được sắp xếp dựa trên các giá trị