Ada teknik yang disebut pembuatan versi yang telah ada selama bertahun-tahun tetapi sebagian besar tidak dapat diterapkan karena beberapa alasan. Namun, ada teknik serupa yang saya sebut sebagai Bentuk Normal Versi yang menurut saya sangat berguna. Berikut adalah contoh penggunaan tabel Karyawan.
Pertama, tabel statis dibuat. Ini adalah tabel entitas utama dan berisi data statis tentang entitas. Data statis adalah data yang diperkirakan tidak akan berubah selama umur entitas, seperti tanggal lahir.
create table Employees(
ID int auto_generated primary key,
FirstName varchar( 32 ),
Hiredate date not null,
TermDate date, -- last date worked
Birthdate date,
... -- other static data
);
Penting untuk menyadari bahwa ada satu entri untuk setiap karyawan, seperti halnya tabel semacam itu.
Kemudian tabel versi terkait. Ini menetapkan hubungan 1-m dengan tabel statis karena mungkin ada beberapa versi untuk seorang karyawan.
create table Employee_versions(
ID int not null,
EffDate date not null,
char( 1 ) IsWorking not null default true,
LastName varchar( 32 ), -- because employees can change last name
PayRate currency not null,
WorkDept int references Depts( ID ),
..., -- other changable data
constraint PK_EmployeeV primary key( ID, EffDate )
);
Dalam catatan tabel versi ada tanggal efektif tetapi bukan bidang yang tidak lagi efektif yang cocok. Ini karena setelah versi berlaku, itu tetap berlaku sampai digantikan oleh versi berikutnya. Kombinasi ID dan EffDate harus unik sehingga tidak boleh ada dua versi untuk karyawan yang sama yang aktif secara bersamaan, juga tidak boleh ada jarak antara waktu satu versi berakhir dan saat versi berikutnya dimulai.
Sebagian besar kueri ingin mengetahui versi data karyawan saat ini. Ini disediakan dengan menggabungkan baris statis untuk karyawan dengan versi yang berlaku sekarang. Ini dapat ditemukan dengan kueri berikut:
select ...
from Employees e
join Employee_versions v1
on v1.ID = e.ID
and v1.EffDate =(
select Max( v2.EffDate )
from EmployeeVersions v2
where v2.ID = v1.ID
and v2.EffDate <= NOW()
)
where e.ID = :EmpID;
Ini mengembalikan satu-satunya versi yang dimulai di masa lalu. Menggunakan pertidaksamaan <=pada pemeriksaan tanggal (v2.EffDate <= NOW()
) memungkinkan tanggal efektif di masa mendatang. Misalkan Anda tahu seorang karyawan baru akan mulai pada hari pertama bulan depan atau kenaikan gaji dijadwalkan pada tanggal 13 bulan depan, data ini dapat dimasukkan sebelumnya. Entri "pramuat" tersebut akan diabaikan.
Jangan biarkan subquery menguasai Anda. Semua bidang pencarian diindeks sehingga hasilnya cukup cepat.
Ada banyak fleksibilitas dengan desain ini. Kueri di atas mengembalikan data terbaru dari semua karyawan, sekarang dan sebelumnya. Anda dapat memeriksa TermDate
lapangan untuk mendapatkan karyawan yang baru saja hadir. Faktanya, karena banyak tempat di aplikasi Anda hanya akan tertarik dengan info terkini dari karyawan saat ini, kueri itu akan menjadi tampilan yang bagus (hilangkan where
akhir ayat). Tidak perlu aplikasi untuk mengetahui versi seperti itu ada.
Jika Anda memiliki tanggal tertentu dan ingin melihat data yang berlaku efektif pada saat itu, ubah v2.EffDate <= NOW()
dalam subkueri ke v2.EffDate <= :DateOfInterest
.
Detail lebih lanjut dapat ditemukan dalam presentasi slide di sini dan dokumen yang tidak lengkap di sini.
Untuk memamerkan sedikit ekstensibilitas desain, perhatikan ada IsWorking
indikator di tabel versi serta tanggal penghentian di tabel statis. Ketika seorang karyawan meninggalkan perusahaan, tanggal terakhir dimasukkan ke dalam tabel statis dan salinan versi terbaru dengan IsWorking
setel ke false
dimasukkan ke dalam tabel versi.
Cukup umum bagi karyawan untuk meninggalkan perusahaan untuk sementara waktu kemudian dipekerjakan lagi. Dengan hanya tanggal di tabel statis, entri dapat diaktifkan kembali hanya dengan mengatur tanggal itu kembali ke NULL. Tetapi kueri "lihat ke belakang" untuk setiap saat ketika orang tersebut tidak lagi menjadi karyawan akan memberikan hasil. Tidak akan ada indikasi bahwa mereka telah meninggalkan perusahaan. Tapi versi dengan IsWorking
=false saat keluar dari perusahaan dan IsWorking
=true saat kembali ke perusahaan akan mengizinkan pemeriksaan nilai tersebut pada saat menarik dan mengabaikan karyawan saat mereka bukan lagi karyawan meskipun mereka kembali lagi nanti.