Pertimbangkan yang berikut ini:
entity User
{
autoincrement uid;
string(20) name;
int privilegeLevel;
}
entity DirectLoginUser
{
inherits User;
string(20) username;
string(16) passwordHash;
}
entity OpenIdUser
{
inherits User;
//Whatever attributes OpenID needs... I don't know; this is hypothetical
}
Berbagai jenis pengguna (pengguna Login Langsung, dan pengguna OpenID) menampilkan hubungan IS-A; yaitu, bahwa kedua jenis pengguna adalah pengguna. Sekarang, ada beberapa cara ini dapat direpresentasikan dalam RDBMS:
Cara Satu
CREATE TABLE Users
(
uid INTEGER AUTO_INCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
privlegeLevel INTEGER NOT NULL,
type ENUM("DirectLogin", "OpenID") NOT NULL,
username VARCHAR(20) NULL,
passwordHash VARCHAR(20) NULL,
//OpenID Attributes
PRIMARY_KEY(uid)
)
Jalan Dua
CREATE TABLE Users
(
uid INTEGER AUTO_INCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
privilegeLevel INTEGER NOT NULL,
type ENUM("DirectLogin", "OpenID") NOT NULL,
PRIMARY_KEY(uid)
)
CREATE TABLE DirectLogins
(
uid INTEGER NOT_NULL,
username VARCHAR(20) NOT NULL,
passwordHash VARCHAR(20) NOT NULL,
PRIMARY_KEY(uid),
FORIGEN_KEY (uid) REFERENCES Users.uid
)
CREATE TABLE OpenIDLogins
(
uid INTEGER NOT_NULL,
// ...
PRIMARY_KEY(uid),
FORIGEN_KEY (uid) REFERENCES Users.uid
)
Jalan Tiga
CREATE TABLE DirectLoginUsers
(
uid INTEGER AUTO_INCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
privlegeLevel INTEGER NOT NULL,
username VARCHAR(20) NOT NULL,
passwordHash VARCHAR(20) NOT NULL,
PRIMARY_KEY(uid)
)
CREATE TABLE OpenIDUsers
(
uid INTEGER AUTO_INCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
privlegeLevel INTEGER NOT NULL,
//OpenID Attributes
PRIMARY_KEY(uid)
)
Saya hampir yakin cara ketiga adalah cara yang salah, karena tidak mungkin untuk melakukan join sederhana terhadap pengguna di tempat lain dalam database.
Contoh dunia nyata saya bukan pengguna dengan contoh login berbeda; Saya tertarik bagaimana memodelkan hubungan ini dalam kasus umum.
database-design
Billy ONeal
sumber
sumber
Jawaban:
Cara kedua adalah cara yang benar.
Kelas dasar Anda mendapatkan tabel, dan kemudian kelas anak mendapatkan tabel mereka sendiri hanya dengan bidang tambahan yang mereka perkenalkan, ditambah referensi kunci asing ke tabel dasar.
Seperti yang disarankan Joel dalam komentarnya pada jawaban ini, Anda dapat menjamin bahwa pengguna akan memiliki login langsung atau login OpenID, tetapi tidak keduanya (dan juga mungkin juga tidak) dengan menambahkan kolom tipe ke setiap tabel sub-tipe yang mengunci kembali ke tabel root. Kolom tipe di setiap sub-tipe tabel dibatasi untuk memiliki nilai tunggal yang mewakili tipe tabel itu. Karena kolom ini adalah kunci asing ke tabel akar, hanya satu baris sub-jenis yang dapat menautkan ke baris akar yang sama pada suatu waktu.
Sebagai contoh, MySQL DDL akan terlihat seperti:
(Pada platform lain, Anda akan menggunakan
CHECK
batasan alih-alihENUM
.) MySQL mendukung kunci asing gabungan sehingga ini harus bekerja untuk Anda.Cara satu valid, meskipun Anda membuang-buang ruang di
NULL
kolom -ableable karena penggunaannya tergantung pada jenis pengguna. Keuntungannya adalah jika Anda memilih untuk memperluas jenis pengguna apa yang akan disimpan dan jenis-jenis itu tidak memerlukan kolom tambahan, Anda bisa memperluas domain AndaENUM
dan menggunakan tabel yang sama.Cara ketiga memaksa kueri yang merujuk pengguna untuk memeriksa kedua tabel. Ini juga mencegah Anda merujuk tabel pengguna tunggal melalui kunci asing.
sumber
UNION
, atau saya akan menyarankan tampilan yang diindeks dengan indeks yang unik terhadapUNION ALL
dariuid
dari dua tabel.)type
kolom ke setiap tabel sub-tipe yang dibatasi melaluiCHECK
kendala untuk memiliki tepat satu nilai (tipe tabel itu). Kemudian, kami membuat kunci asing sub-tabel ke super-tabel menjadi yang komposit pada keduanyauid
dantype
. Itu cerdik.Mereka akan diberi nama
dan semua memiliki kegunaan yang sah dan didukung oleh beberapa perpustakaan. Anda harus mencari tahu mana yang paling cocok.
Memiliki beberapa tabel akan membuat manajemen data lebih memperhatikan kode aplikasi Anda tetapi akan mengurangi jumlah ruang yang tidak digunakan.
sumber