Saya cukup yakin banyak aplikasi, aplikasi kritis, bank dan sebagainya melakukan ini setiap hari.
Gagasan di balik semua itu adalah:
- semua baris harus memiliki riwayat
- semua tautan harus tetap koheren
- seharusnya mudah untuk membuat permintaan untuk mendapatkan kolom "saat ini"
- klien yang telah membeli barang-barang usang masih harus melihat apa yang telah mereka beli meskipun produk ini bukan bagian dari katalog lagi
dan seterusnya.
Inilah yang ingin saya lakukan, dan saya akan menjelaskan masalah yang saya hadapi.
Semua tabel saya akan memiliki kolom-kolom itu:
id
id_origin
date of creation
start date of validity
start end of validity
Dan inilah ide untuk operasi CRUD:
- buat = masukkan baris baru dengan
id_origin
=id
,date of creation
= sekarang,start date of validity
= sekarang,end date of validity
= null (= berarti ini adalah rekaman aktif saat ini) - pembaruan =
- baca = baca semua catatan dengan
end date of validity
== null - perbarui catatan "saat ini"
end date of validity
= null denganend date of validity
= sekarang - buat yang baru dengan nilai-nilai baru, dan
end date of validity
= null (= berarti ini adalah rekaman aktif saat ini)
- baca = baca semua catatan dengan
- delete = perbarui catatan "saat ini"
end date of validity
= null denganend date of validity
= sekarang
Jadi, inilah masalah saya: dengan banyak asosiasi. Mari kita ambil contoh dengan nilai:
- Tabel A (id = 1, id_origin = 1, mulai = sekarang, akhir = nol)
- Tabel A_B (mulai = sekarang, akhir = nol, id_A = 1, id_B = 48)
- Tabel B (id = 48, id_origin = 48, mulai = sekarang, akhir = nol)
Sekarang saya ingin memperbarui tabel A, record id = 1
- Saya menandai catatan id = 1 dengan ujung = sekarang
Saya memasukkan nilai baru ke dalam tabel A dan ... sialan saya telah kehilangan relasi saya A_B kecuali jika saya menduplikasi relasinya juga ... ini akan berakhir pada tabel:
Tabel A (id = 1, id_origin = 1, mulai = sekarang, akhir = sekarang + 8juta)
- Tabel A (id = 2, id_origin = 1, mulai = sekarang + 8 juta, akhir = nol)
- Tabel A_B (mulai = sekarang, akhir = nol, id_A = 1, id_B = 48)
- Tabel A_B (mulai = sekarang, akhir = nol, id_A = 2, id_B = 48)
- Tabel B (id = 48, id_origin = 48, mulai = sekarang, akhir = nol)
Dan ... yah saya punya masalah lain: hubungan A_B: haruskah saya tandai (id_A = 1, id_B = 48) sebagai usang atau tidak (A - id = 1 sudah usang, tetapi bukan B - 48)?
Bagaimana cara menghadapinya?
Saya harus merancang ini dalam skala besar: produk, mitra, dan sebagainya.
Apa pengalaman Anda dalam hal ini? Bagaimana yang akan Anda lakukan (bagaimana Anda melakukannya)?
- Edit
Saya telah menemukan artikel yang sangat menarik ini , tetapi tidak berurusan dengan "usang usang" (= apa yang sebenarnya saya tanyakan)
sumber
Jawaban:
Tidak jelas bagi saya apakah persyaratan ini untuk tujuan audit atau hanya referensi sejarah sederhana seperti dengan CRM dan keranjang belanja.
Either way, pertimbangkan memiliki tabel main dan main_archive untuk setiap area utama di mana ini diperlukan. "Utama" hanya akan memiliki entri saat ini / aktif sedangkan "main_archive" akan memiliki salinan semua yang pernah masuk ke utama. Sisipkan / perbarui ke main_archive dapat menjadi pemicu dari memasukkan / memperbarui ke utama. Menghapus terhadap main_archive kemudian dapat berjalan melintasi periode waktu yang lebih lama, jika pernah.
Untuk masalah referensial seperti Cust X membeli Produk Y, cara termudah untuk menyelesaikan masalah referensial Anda dari cust_archive -> product_archive adalah tidak pernah menghapus entri dari product_archive. Secara umum, churn harus jauh lebih rendah di meja itu sehingga ukurannya tidak terlalu buruk.
HTH.
sumber
LP_
, dan setiap tabel penting memiliki yang setaraLH_
, dengan pemicu menyisipkan baris historis pada menyisipkan, memperbarui, menghapus. Ini tidak berfungsi untuk semua kasus tetapi sudah menjadi model yang solid untuk hal-hal yang saya lakukan.UNION
tampilan itu, yang memungkinkan Anda melakukan hal-hal keren seperti memberlakukan batasan unik di kedua catatan saat ini dan sejarah.id
", dan "id_ref
".id_ref
adalah referensi ke ide sebenarnya dari tabel. Contoh:person
danperson_h
. diperson_h
saya punya "id
", dan "id_ref
" di manaid_ref
terkait dengan 'person.id
' jadi saya dapat memiliki banyak baris dengan yang samaperson.id
(= ketika satu barisperson
dimodifikasi) dan semuaid
tabel saya semuanya otomatis.Ini memiliki beberapa tumpang tindih dengan pemrograman fungsional; khususnya konsep kekekalan.
Anda memiliki satu tabel yang dipanggil
PRODUCT
dan yang lainnya disebutPRODUCTVERSION
atau serupa. Ketika Anda mengganti produk yang tidak Anda lakukan pembaruan, Anda cukup memasukkanPRODUCTVERSION
baris baru . Untuk mendapatkan yang terbaru, Anda dapat mengindeks tabel dengan nomor versi (desc), timestamp (desc), atau Anda dapat memiliki bendera (LatestVersion
).Sekarang jika Anda memiliki sesuatu yang mereferensikan suatu produk, Anda dapat memutuskan tabel mana yang ditunjuknya. Apakah itu menunjuk ke
PRODUCT
entitas (selalu merujuk ke produk ini) atau kePRODUCTVERSION
entitas (hanya merujuk ke versi produk ini)?Itu jadi rumit. Bagaimana jika Anda memiliki gambar produk? Mereka harus menunjuk ke tabel versi, karena mereka dapat diubah, tetapi dalam banyak kasus, mereka tidak akan dan Anda tidak ingin menggandakan data yang tidak perlu. Itu berarti Anda membutuhkan
PICTURE
meja dan hubunganPRODUCTVERSIONPICTURE
banyak-ke-banyak.sumber
Saya sudah menerapkan semua hal dari sini dengan 4 bidang yang ada di semua tabel saya:
Setiap kali catatan harus dimodifikasi, saya menduplikatnya, menandai catatan yang digandakan sebagai "lama" =
date_validity_end=NOW()
dan yang sekarang sebagai yang baikdate_validity_start=NOW()
dandate_validity_end=NULL
.Triknya adalah tentang hubungan banyak ke banyak dan satu ke banyak: itu bekerja tanpa menyentuh mereka! Ini semua tentang kueri yang lebih kompleks: untuk meminta catatan pada tanggal yang tepat (= tidak sekarang), saya punya untuk setiap bergabung, dan untuk tabel utama, untuk menambahkan kendala-kendala itu:
Begitu juga dengan produk dan atribut (banyak ke banyak hubungan):
sumber
Bagaimana dengan ini? Tampaknya sederhana dan cukup efektif untuk apa yang telah saya lakukan di masa lalu. Di tabel "riwayat" Anda, gunakan PK yang berbeda. Jadi, bidang "CustomerID" Anda adalah PK di tabel Pelanggan Anda, tetapi di tabel "history", PK Anda adalah "NewCustomerID". "CustomerID" menjadi bidang hanya baca lainnya. Itu membuat "CustomerID" tidak berubah dalam Riwayat dan semua hubungan Anda tetap utuh.
sumber