Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Terapkan batasan unik komposit yang bergantung pada nilai kolom induk

Saya percaya bahwa ini adalah salah satu kasus langka di mana penggunaan kunci pengganti (auto_increment id's) alih-alih kunci alami telah menyesatkan Anda. Pertimbangkan bagaimana definisi tabel Anda akan terlihat jika Anda menggunakan kunci alami sebagai gantinya:

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)
)

Sekarang Anda dapat menambahkan kursi yang dipesan per batasan yang ditampilkan sebagai Kunci Alternatif di reservasi_kursi:

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)
)

Namun, ini memperjelas bahwa kunci utama tidak berguna karena itu hanyalah versi yang lebih lemah dari batasan yang telah kami tambahkan, jadi kami harus menggantinya dengan batasan baru kami.

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)
)

Kami mungkin khawatir sekarang bahwa reservation_seat kami dapat mereferensikan reservasi dengan show_id yang berbeda dari reservation_seat itu sendiri, tetapi itu tidak menjadi masalah untuk kunci alami karena referensi kunci asing pertama mencegah hal itu.

Sekarang yang perlu kita lakukan adalah menerjemahkannya kembali menjadi kunci pengganti:

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)
)

Karena kita membuat reservasi_seat(id) sebagai kunci utama, kita harus mengubah definisi PK bernama kembali menjadi batasan unik. Dibandingkan dengan definisi reservasi_kursi asli Anda, kami berakhir dengan menambahkan show_id, tetapi dengan definisi kunci asing pertama yang lebih kuat yang dimodifikasi, kami sekarang memastikan bahwa reservasi_kursi adalah unik dalam tampilan dan bahwa reservasi_kursi tidak dapat memiliki show_id yang berbeda dari reservasi induknya.

(Catatan:Anda mungkin harus mengutip nama kolom 'baris' dan 'kolom' dalam kode SQL di atas)

Catatan Tambahan: DBMS bervariasi dalam hal ini (dan saya tidak yakin tentang MySql dalam kasus ini), tetapi banyak yang akan mengharuskan hubungan Kunci Asing memiliki Kunci Utama atau Batasan Unik yang sesuai pada tabel target (direferensikan). Ini berarti Anda harus mengubah reservasi tabel dengan batasan baru seperti:

CONSTRAINT UC_showing_reserved UNIQUE(showing_id, id)

untuk mencocokkan definisi FK baru di reservation_seat yang saya sarankan di atas:

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

Secara teknis, ini akan menjadi kendala yang berlebihan karena ini adalah versi yang lebih lemah dari kunci utama pada tabel reservasi, tetapi dalam kasus ini SQL mungkin masih memerlukannya untuk mengimplementasikan 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. Memahami beberapa indeks kolom dalam kueri MySQL

  2. Sertifikasi SSL yang ditandatangani sendiri untuk terhubung dengan Mysql dengan PHP

  3. konversi tanggal string python ke datetime mysql

  4. mysql yang nilainya memiliki jumlah maksimum

  5. Menambahkan kolom SQL baru dengan nilai default