Memiliki tabel referensi di database Anda bukanlah masalah besar, bukan? Anda hanya perlu mengikat kode atau ID dengan deskripsi untuk setiap jenis referensi. Tetapi bagaimana jika Anda benar-benar memiliki lusinan tabel referensi? Apakah ada alternatif untuk pendekatan satu tabel per tipe? Baca terus untuk menemukan umum dan dapat diperluas desain database untuk menangani semua data referensi Anda.
Diagram yang tampak tidak biasa ini adalah pandangan luas dari model data logis (LDM) yang berisi semua jenis referensi untuk sistem perusahaan. Ini dari lembaga pendidikan, tetapi dapat diterapkan pada model data dari organisasi apa pun. Semakin besar modelnya, semakin banyak jenis referensi yang mungkin Anda temukan.
Dengan tipe referensi yang saya maksud adalah data referensi, atau nilai pencarian, atau – jika Anda ingin menjadi flash – taksonomi . Biasanya, nilai yang ditentukan di sini digunakan dalam daftar drop-down di antarmuka pengguna aplikasi Anda. Mereka juga dapat muncul sebagai judul pada laporan.
Model data khusus ini memiliki sekitar 100 tipe referensi. Mari kita perbesar dan lihat hanya dua di antaranya.
Dari diagram kelas ini, kita melihat bahwa semua tipe referensi memperluas Root_Reference_Type
. Dalam praktiknya, ini hanya berarti bahwa semua tipe referensi kami memiliki atribut yang sama dari Alt_Sequence
melalui Type_Key
inklusif, seperti yang ditunjukkan di bawah ini.
Atribut | Deskripsi |
---|---|
Alt_Sequence | Digunakan untuk menentukan urutan alternatif ketika urutan non-abjad diperlukan. |
Description | Deskripsi jenisnya. |
Effective_Period | Secara efektif menentukan apakah entri referensi diaktifkan atau tidak. Setelah referensi digunakan, referensi tidak dapat dihapus karena batasan referensial; itu hanya dapat dinonaktifkan. |
| Nama yang cantik untuk tipenya. Inilah yang dilihat pengguna di layar. |
Type_Key | KUNCI internal yang unik untuk tipe tersebut. Ini disembunyikan dari pengguna tetapi pengembang aplikasi dapat menggunakan ini secara ekstensif dalam SQL mereka. |
Jenis partai di sini adalah organisasi atau orang. Jenis kelaminnya adalah laki-laki dan perempuan. Jadi ini adalah kasus yang sangat sederhana.
Solusi Tabel Referensi Tradisional
Jadi bagaimana kita akan menerapkan model logis di dunia fisik dari database yang sebenarnya?
Kita dapat mengambil pandangan bahwa setiap tipe referensi akan dipetakan ke tabelnya sendiri. Anda mungkin menyebut ini sebagai satu meja-per-kelas yang lebih tradisional larutan. Cukup sederhana, dan akan terlihat seperti ini:
Sisi negatifnya adalah mungkin ada lusinan tabel ini, semuanya memiliki kolom yang sama, semuanya melakukan hal yang sama.
Selanjutnya, kami mungkin membuat lebih banyak pekerjaan pengembangan . Jika UI untuk setiap jenis diperlukan bagi administrator untuk mempertahankan nilai, maka jumlah pekerjaan akan berlipat ganda dengan cepat. Tidak ada aturan keras dan cepat untuk ini – ini sangat bergantung pada lingkungan pengembangan Anda – jadi Anda harus berbicara dengan pengembang Anda untuk memahami apa dampaknya.
Tetapi mengingat bahwa semua tipe referensi kami memiliki atribut, atau kolom yang sama, apakah ada cara yang lebih umum untuk menerapkan model data logis kami? Ya ada! Dan hanya membutuhkan dua tabel .
Solusi Dua Meja
Diskusi pertama yang pernah saya lakukan tentang subjek ini adalah pada pertengahan 90-an, ketika saya bekerja untuk sebuah perusahaan asuransi London Market. Saat itu, kami langsung menuju ke desain fisik dan sebagian besar menggunakan kunci alami/bisnis, bukan ID. Jika ada data referensi, kami memutuskan untuk menyimpan satu tabel per jenis yang terdiri dari kode unik (VARCHAR PK) dan deskripsi. Faktanya, tabel referensi saat itu jauh lebih sedikit. Lebih sering daripada tidak, seperangkat kode bisnis terbatas akan digunakan dalam kolom, mungkin dengan batasan pemeriksaan database yang ditentukan; tidak akan ada tabel referensi sama sekali.
Tapi permainan telah pindah sejak saat itu. Inilah solusi dua meja mungkin terlihat seperti:
Seperti yang Anda lihat, model data fisik ini sangat sederhana. Tapi itu sangat berbeda dari model logis, dan bukan karena sesuatu telah menjadi seperti buah pir. Itu karena sejumlah hal dilakukan sebagai bagian dari desain fisik .
reference_type
tabel mewakili setiap kelas referensi individu dari LDM. Jadi, jika Anda memiliki 20 jenis referensi di LDM, Anda akan memiliki 20 baris meta-data dalam tabel. reference_value
tabel berisi nilai yang diizinkan untuk semua jenis referensi.
Pada saat proyek ini, ada beberapa diskusi yang cukup hidup antara pengembang. Beberapa menyukai solusi dua tabel dan yang lainnya lebih menyukai satu tabel per tipe metode.
Ada pro dan kontra untuk setiap solusi. Seperti yang Anda duga, sebagian besar pengembang khawatir dengan jumlah pekerjaan yang akan dilakukan UI. Beberapa orang berpikir bahwa menyatukan UI admin untuk setiap tabel akan cukup cepat. Yang lain berpikir bahwa membangun UI admin tunggal akan lebih kompleks tetapi pada akhirnya membuahkan hasil.
Pada proyek khusus ini, solusi dua meja lebih disukai. Mari kita lihat lebih detail.
Pola Data Referensi yang Dapat Diperluas dan Fleksibel
Karena model data Anda berkembang dari waktu ke waktu dan tipe referensi baru diperlukan, Anda tidak perlu terus membuat perubahan pada database Anda untuk setiap tipe referensi baru. Anda hanya perlu mendefinisikan data konfigurasi baru. Untuk melakukannya, tambahkan baris baru ke reference_type
tabel dan tambahkan daftar terkontrol dari nilai yang diizinkan ke reference_value
tabel.
Konsep penting yang terkandung dalam solusi ini adalah mendefinisikan periode waktu efektif untuk nilai-nilai tertentu. Misalnya, organisasi Anda mungkin perlu menangkap reference_value
dari 'Bukti ID' yang akan diterima di masa mendatang. Ini adalah masalah sederhana untuk menambahkan reference_value
dengan effective_period_from
tanggal ditetapkan dengan benar. Hal ini dapat dilakukan terlebih dahulu. Sampai tanggal itu tiba, entri baru tidak akan muncul di daftar drop-down nilai yang dilihat pengguna aplikasi Anda. Ini karena aplikasi Anda hanya menampilkan nilai yang terkini, atau diaktifkan.
Di sisi lain, Anda mungkin perlu menghentikan pengguna menggunakan reference_value
. Dalam hal ini, cukup perbarui dengan effective_period_to
tanggal ditetapkan dengan benar. Ketika hari itu berlalu, nilainya tidak akan muncul lagi di daftar drop-down. Ini menjadi dinonaktifkan sejak saat itu. Tetapi karena masih ada secara fisik sebagai baris dalam tabel, integritas referensial dipertahankan untuk tabel yang telah dirujuk.
Sekarang setelah kami mengerjakan solusi dua tabel, menjadi jelas bahwa beberapa kolom tambahan akan berguna pada reference_type
meja. Ini sebagian besar berpusat pada masalah UI.
Misalnya, pretty_name
pada reference_type
tabel telah ditambahkan untuk digunakan di UI. Akan sangat membantu bagi taksonomi besar untuk menggunakan jendela dengan fungsi pencarian. Kemudian pretty_name
dapat digunakan untuk judul jendela.
Di sisi lain, jika daftar drop-down nilai sudah cukup, pretty_name
dapat digunakan untuk prompt LOV. Dengan cara yang sama, deskripsi dapat digunakan di UI untuk mengisi bantuan roll-over.
Melihat jenis konfigurasi atau meta-data yang masuk ke dalam tabel ini akan sedikit membantu memperjelas beberapa hal.
Cara Mengelola Semua Itu
Sementara contoh yang digunakan di sini sangat sederhana, nilai referensi untuk proyek besar dapat dengan cepat menjadi sangat kompleks. Jadi mungkin disarankan untuk menyimpan semua ini dalam spreadsheet. Jika demikian, Anda dapat menggunakan spreadsheet itu sendiri untuk menghasilkan SQL menggunakan rangkaian string. Ini ditempelkan ke skrip, yang dijalankan terhadap database target yang mendukung siklus hidup pengembangan dan database produksi (langsung). Ini menyemai database dengan semua data referensi yang diperlukan.
Berikut data konfigurasi untuk kedua tipe LDM tersebut, Gender_Type
dan Party_Type
:
PROMPT Gender_Type INSERT INTO reference_type (id, pretty_name, ref_type_key, description, id_range_from, id_range_to) VALUES (rety_seq.nextval, 'Gender Type', 'GENDER_TYPE', ' Identifies the gender of a person.', 13000000, 13999999); INSERT INTO reference_value (id, pretty_name, description, effective_period_from, alt_sequence, reference_type_id) VALUES (13000010,'Female', 'Female', TRUNC(SYSDATE), 10, rety_seq.currval); INSERT INTO reference_value (id, pretty_name, description, effective_period_from, alt_sequence, reference_type_id) VALUES (13000020,'Male', 'Male', TRUNC(SYSDATE), 20, rety_seq.currval); PROMPT Party_Type INSERT INTO reference_type (id, pretty_name, ref_type_key, description, id_range_from, id_range_to) VALUES (rety_seq.nextval, 'Party Type', 'PARTY_TYPE', A controlled list of reference values that identifies the type of party.', 23000000, 23999999); INSERT INTO reference_value (id, pretty_name, description, effective_period_from, alt_sequence, reference_type_id) VALUES (23000010,'Organisation', 'Organisation', TRUNC(SYSDATE), 10, rety_seq.currval); INSERT INTO reference_value (id, pretty_name, description, effective_period_from, alt_sequence, reference_type_id) VALUES (23000020,'Person', 'Person', TRUNC(SYSDATE), 20, rety_seq.currval);
Ada baris di reference_type
untuk setiap subtipe LDM dari Root_Reference_Type
. Deskripsi di reference_type
diambil dari deskripsi kelas LDM. Untuk Gender_Type
, ini akan berbunyi "Mengidentifikasi jenis kelamin seseorang". Cuplikan DML menunjukkan perbedaan deskripsi antara jenis dan nilai, yang dapat digunakan di UI atau dalam laporan.
Anda akan melihat reference_type
disebut Gender_Type
telah dialokasikan kisaran 13000000 hingga 13999999 untuk reference_value.ids
terkaitnya . Dalam model ini, setiap reference_type
dialokasikan rentang ID yang unik dan tidak tumpang tindih. Ini tidak sepenuhnya diperlukan, tetapi memungkinkan kita untuk mengelompokkan ID nilai terkait bersama-sama. Ini semacam meniru apa yang Anda dapatkan jika Anda memiliki tabel terpisah. Ini bagus untuk dimiliki, tetapi jika menurut Anda tidak ada manfaatnya, Anda dapat membuangnya.
Kolom lain yang ditambahkan ke PDM adalah admin_role
. Inilah alasannya.
Siapa Administratornya
Beberapa taksonomi dapat memiliki nilai tambah atau hapus dengan sedikit atau tanpa dampak. Ini akan terjadi ketika tidak ada program yang menggunakan nilai dalam logikanya, atau ketika tipe tidak dihubungkan ke sistem lain. Dalam kasus seperti itu, administrator pengguna aman untuk selalu memperbaruinya.
Tetapi dalam kasus lain, lebih banyak perawatan perlu dilakukan. Nilai referensi baru dapat menyebabkan konsekuensi yang tidak diinginkan pada logika program atau sistem hilir.
Misalnya, kita tambahkan berikut ini ke taksonomi Jenis Gender:
INSERT INTO reference_value (id, pretty_name, description, effective_period_from, alt_sequence, reference_type_id) VALUES (13000040,'Not Known', 'Gender has not been recorded. Covers gender of unborn child, when someone has refused to answer the question or when the question has not been asked.', TRUNC(SYSDATE), 30, (SELECT id FROM reference_type WHERE ref_type_key = 'GENDER_TYPE'));
Ini dengan cepat menjadi masalah jika kita memiliki logika berikut yang dibangun di suatu tempat:
IF ref_key = 'MALE' THEN RETURN 'M'; ELSE RETURN 'F'; END IF;
Jelas, logika "jika Anda bukan laki-laki, Anda harus perempuan" tidak lagi berlaku dalam taksonomi yang diperluas.
Di sinilah admin_role
kolom ikut bermain. Itu lahir dari diskusi dengan pengembang tentang desain fisik, dan itu bekerja bersama dengan solusi UI mereka. Tetapi jika solusi satu tabel per kelas telah dipilih, maka reference_type
tidak akan ada. Meta-data yang dikandungnya akan di-hard-code ke dalam aplikasi Gender_Type
table – , yang tidak fleksibel atau dapat diperluas.
Hanya pengguna dengan hak istimewa yang benar yang dapat mengelola taksonomi. Ini kemungkinan didasarkan pada keahlian materi pelajaran (UKM ). Di sisi lain, beberapa taksonomi mungkin perlu dikelola oleh TI untuk memungkinkan analisis dampak, pengujian menyeluruh, dan agar setiap perubahan kode dirilis secara harmonis pada waktunya untuk konfigurasi baru. (Apakah ini dilakukan dengan permintaan perubahan atau dengan cara lain terserah organisasi Anda.)
Anda mungkin telah memperhatikan bahwa kolom audit created_by
, created_date
, updated_by
, dan updated_date
tidak dirujuk sama sekali dalam skrip di atas. Sekali lagi, jika Anda tidak tertarik dengan ini, Anda tidak perlu menggunakannya. Organisasi khusus ini memiliki standar yang mengamanatkan memiliki kolom audit di setiap meja.
Pemicu:Menjaga Segalanya Konsisten
Pemicu memastikan bahwa kolom audit ini diperbarui secara konsisten, apa pun sumber SQLnya (skrip, aplikasi Anda, pembaruan batch terjadwal, pembaruan ad-hoc, dll.).
-------------------------------------------------------------------------------- PROMPT >>> create REFERENCE_TYPE triggers -------------------------------------------------------------------------------- CREATE OR REPLACE TRIGGER rety_bri BEFORE INSERT ON reference_type FOR EACH ROW DECLARE BEGIN IF (:new.id IS NULL) THEN :new.id := rety_seq.nextval; END IF; :new.created_by := function_to_get_user(); :new.created_date := SYSDATE; :new.updated_by := :new.created_by; :new.updated_date := :new.created_date; END rety_bri; / CREATE OR REPLACE TRIGGER rety_bru BEFORE UPDATE ON reference_type FOR EACH ROW DECLARE BEGIN :new.updated_by := function_to_get_user(); :new.updated_date := SYSDATE; END rety_bru; / -------------------------------------------------------------------------------- PROMPT >>> create REFERENCE_VALUE triggers -------------------------------------------------------------------------------- CREATE OR REPLACE TRIGGER reva_bri BEFORE INSERT ON reference_value FOR EACH ROW DECLARE BEGIN IF (:new.type_key IS NULL) THEN -- create the type_key from pretty_name: :new.type_key := function_to_create_key(new.pretty_name); END IF; :new.created_by := function_to_get_user(); :new.created_date := SYSDATE; :new.updated_by := :new.created_by; :new.updated_date := :new.created_date; END reva_bri; / CREATE OR REPLACE TRIGGER reva_bru BEFORE UPDATE ON reference_value FOR EACH ROW DECLARE BEGIN -- once the type_key is set it cannot be overwritten: :new.type_key := :old.type_key; :new.updated_by := function_to_get_user(); :new.updated_date := SYSDATE; END reva_bru; /
Latar belakang saya sebagian besar Oracle dan, sayangnya, Oracle membatasi pengidentifikasi hingga 30 byte. Untuk menghindari melebihi ini, setiap tabel diberi alias pendek dari tiga sampai lima karakter dan artefak terkait tabel lainnya menggunakan alias itu dalam namanya. Jadi, reference_value
aliasnya adalah reva
– dua karakter pertama dari setiap kata. Sebelum menyisipkan baris dan sebelum pembaruan baris disingkat menjadi bri
dan bru
masing-masing. Nama urutan reva_seq
, dan seterusnya.
Pemicu pengkodean tangan seperti ini, tabel demi tabel, membutuhkan banyak pekerjaan boiler-plate yang melemahkan semangat pengembang. Untungnya, pemicu ini dapat dibuat melalui pembuatan kode , tapi itu topik artikel lain!
Pentingnya Tombol
ref_type_key
dan type_key
kolom keduanya dibatasi hingga 30 byte. Ini memungkinkan mereka untuk digunakan dalam kueri SQL tipe PIVOT (di Oracle. Basis data lain mungkin tidak memiliki batasan panjang pengenal yang sama).
Karena keunikan kunci dipastikan oleh database dan pemicu memastikan bahwa nilainya tetap sama sepanjang waktu, kunci ini dapat – dan harus – digunakan dalam kueri dan kode untuk membuatnya lebih mudah dibaca . Apa yang saya maksud dengan ini? Nah, alih-alih:
SELECT … FROM … INNER JOIN … WHERE reference_value.id = 13000020
Anda menulis:
SELECT … FROM … INNER JOIN … WHERE reference_value.type_key = 'MALE'
Pada dasarnya, kunci menjelaskan dengan jelas apa yang dilakukan kueri .
Dari LDM ke PDM, dengan Ruang untuk Tumbuh
Perjalanan dari LDM ke PDM belum tentu jalan lurus. Juga bukan transformasi langsung dari satu ke yang lain. Ini adalah proses terpisah yang memperkenalkan pertimbangan dan perhatiannya sendiri.
Bagaimana Anda memodelkan data referensi dalam database Anda?