Bagaimana cara mendesain basis data ini untuk menghindari ketergantungan siklik?

12

Ada dua tabel:

  1. Pengguna
  2. Alamat

Pengguna berisi referensi ke Alamat.

Alamat berisi kolom CreatedBy dan ModifiedBy, yang merujuk pada Pengguna.

Bagaimana cara mendesain database ini untuk menghindari ketergantungan siklik?

Shashi
sumber
4
Apakah Anda yakin ModifiedBy bukan referensi ke pengguna basis data yang melakukan perubahan, alih-alih pengguna aplikasi (yang akan berada di tabel Pengguna)? Either way, itu tidak terlalu penting. Saya tidak melihat mengapa ada masalah aktual?
Philᵀᴹ
Yang mana yang akan dibuat terlebih dahulu. Sebagai CreatedBy dan Dimodifikasi oleh adalah suatu keharusan data. Dan tabel pengguna seharusnya tidak memiliki addressid sebagai nol .. Masalah ayam-telur. Saat saya menyelesaikan ini dengan membuat tabel baru UserAddress yang berisi referensi untuk userid dan addressid
Shashi
2
Anda selalu dapat menggunakan batasan yang ditangguhkan jika DBMS Anda mendukungnya.
Colin 't Hart
NB Model relasional mendukung melakukan dua menyisipkan atau memperbarui sebagai satu operasi atom, sungguh memalukan ini tidak didukung dalam SQL (seperti batasan yang ditangguhkan - meskipun saya menyarankan mereka - cukup mengerikan).
Colin 't Hart

Jawaban:

7

Alih-alih mencari tips dan trik (termasuk kendala yang ditangguhkan), saya sarankan Anda mendesain jalan keluar dari "kunci referensi" ini - jadi cobalah sesuatu seperti ini:


Fakta

  • Pengguna(UserID) ada.
  • Alamat(AddressID) dibuat oleh Pengguna(UserID) .
  • Alamat(AddressID) dibuat pada Tanggal(DateCreated) .
  • Alamat(AddressID) terakhir diubah oleh Pengguna(UserID) pada Tanggal(ModifiedOn) .
  • Pengguna(UserID) berada di Alamat(AddressID) sejak Tanggal(ValidFrom) .

Kendala

  • Each Alamat dibuat oleh exactly one Pengguna . It is possible that more than one Alamat dibuat oleh the same Pengguna .

  • Each Alamat dibuat pada exactly one Tanggal . It is possible that more than one Alamat dibuat pada the same Tanggal .

  • For each and Tanggal Alamat , that Alamat diubah oleh at most one Pengguna pada that Tanggal .

  • For each and Tanggal Pengguna , that Pengguna berada di at most one Alamat sejak that Tanggal .


Logis

masukkan deskripsi gambar di sini


Sejauh menyangkut alamat wajib, verifikasi bahwa pada lapisan aplikasi dan bungkus pernyataan pemuatan menjadi transaksi - dengan cara itu Anda akan mendapatkan semua atau tidak sama sekali.

Damir Sudarevic
sumber
5

Anda tidak punya pilihan selain membuat ketergantungan siklik dalam 2 operasi seperti di bawah ini karena satu tabel tidak ada ketika Anda membuat yang pertama.

CREATE TABLE A (A_ID INT PRIMARY KEY, B_FK INT);
CREATE TABLE B (B_ID INT PRIMARY KEY, A_FK INT REFERENCES A(A_ID));

ALTER TABLE A ADD B_FK INT;

Jika Anda ingin menghindari ketergantungan siklik. Maka Anda perlu menghapus satu batasan REFERENSI atau Anda dapat menambahkan referensi DELETE dan UPDATE CASCADE dalam satu cara. Anda juga bisa mengimplementasikan TRIGGER jika logika Anda agak rumit.

PollusB
sumber
1
Menghapus kendala menghilangkan ketergantungan siklik dari definisi, tetapi tidak pada desain. Anda bisa menambahkan tabel Acara untuk merekam UserID dan AddressID yang terakhir dibuat atau diubah alamat, tetapi itu hanya memindahkan ketergantungan satu langkah lebih jauh. Ke arah lain, jika tabel Pengguna memiliki kolom CreatedBy dan ModifiedBy, ketergantungan siklik akan ada dalam satu tabel. Ini mirip dengan meja karyawan dengan kolom pengawas di mana pengawas juga seorang karyawan. Seperti yang ditunjukkan Phil - Tidak masalah.
Leigh Riffel
@LeighRiffel Saya setuju. Tetapi tabel Acara yang Anda usulkan benar-benar menghapus semua dependensi siklik.
ypercubeᵀᴹ
@ ypercube Memang benar; tidak yakin bagaimana saya dapat melewati kawat itu. Agar lebih jelas, Anda mungkin tidak harus membuat tabel Acara meskipun itu menghapus ketergantungan siklik.
Leigh Riffel
Bagaimanapun, saya tidak berpikir jawaban ini mengatasi masalah. Pertanyaannya (saya pikir) adalah tentang bagaimana menghindari jalur siklik sama sekali, bukan bagaimana membuat FK dengan jalur siklik di tempat pertama.
ypercubeᵀᴹ