Tidak tahu bagaimana mengubah entitas variabel menjadi tabel relasional

9

PENDAHULUAN DAN INFORMASI YANG RELEVAN:

Contoh berikut menggambarkan masalah yang saya hadapi:

Hewan memiliki ras, yang bisa berupa kucing atau anjing . Kucing dapat berupa Siam atau Persia . Anjing bisa menjadi gembala Jerman atau Labrador retriver .

Hewan adalah entitas yang kuat, sementara rasnya adalah atribut yang dapat memiliki salah satu dari dua nilai yang ditawarkan (kucing atau anjing). Kedua nilai ini kompleks (saya telah menambahkan di sini hanya jenis anjing / kucing untuk menggambarkan masalah, tetapi bisa juga ada nama kucing / anjing dan banyak hal lainnya).

MASALAH:

Saya tidak tahu cara membuat tabel relasional untuk contoh ini.

UPAYA SAYA UNTUK MEMECAHKAN MASALAH:

Saya telah mencoba menggambar diagram ER, menggunakan notasi Chen, yang merepresentasikan masalah tetapi sebagai seorang pemula saya tidak tahu apakah saya melakukannya dengan benar. Inilah yang saya dapatkan:

masukkan deskripsi gambar di sini

Saya minta maaf jika saya melakukan kesalahan, mohon perbaiki jika itu masalahnya. Saya tidak ingin hanya mendapatkan "solusi gratis" tetapi juga belajar bagaimana menangani masalah ini sehingga saya dapat menyelesaikannya sendiri di masa depan.

Satu-satunya hal yang terlintas di pikiran saya adalah membuat dua tabel terpisah, satu untuk kucing dan satu untuk anjing. Juga, atribut ras dalam tabel Animal hanya akan menyimpan nilai kucing atau anjing . Sesuatu seperti ini:

Animal< # Animal_ID, race, other attributes >
Cat < # Cat_ID, $ Animal_ID, breed >
Dog < # Dog_ID, $ Animal_ID, breed >

Saya benar-benar memiliki perasaan buruk tentang solusi saya dan saya khawatir itu salah, maka pertanyaan di bawah ini.

PERTANYAAN:

  • Bagaimana saya bisa mengubah contoh saya menjadi diagram ER?
  • Bagaimana cara mengubah diagram ER menjadi tabel relasional?

Jika info lebih lanjut diperlukan tinggalkan komentar dan saya akan memperbarui posting saya sesegera mungkin. Juga merasa bebas untuk menambahkan tag yang sesuai karena saya cukup baru di sini.

Terima kasih.

AlwaysLearningNewStuff
sumber
1
Transformasi diagram EER ke tabel dapat ditemukan dalam makalah ini dari tahun 1986 dari TJTeorey, D.Yang, JPFry: Metodologi Desain Logis untuk Database Relasional Menggunakan Extended Entity-Relationship Model . Sangat mudah dan salah satu makalah favorit saya.
miracle173

Jawaban:

11

Struktur yang tepat untuk skenario ini adalah model SubClass / Inheritance, dan hampir identik dengan konsep yang saya usulkan dalam jawaban ini: Daftar nilai yang diurutkan secara heterogen .

Model yang diajukan dalam pertanyaan ini sebenarnya cukup dekat karena Animalentitas berisi tipe (yaitu race) dan properti yang umum di semua tipe. Namun, ada dua perubahan kecil yang diperlukan:

  1. Hapus bidang Cat_ID dan Dog_ID dari entitasnya masing-masing:

    Konsep kunci di sini adalah bahwa segala sesuatu adalah Animal, terlepas dari race: Cat, Dog, Elephant, dan sebagainya. Mengingat titik awal itu, setiap bagian racedari Animaltidak benar-benar memerlukan pengidentifikasi terpisah karena:

    1. yang Animal_IDunik
    2. yang Cat, Dog, dan setiap tambahan raceentitas ditambahkan di masa depan tidak, dengan sendirinya, sepenuhnya mewakili tertentu Animal; mereka hanya memiliki makna ketika digunakan dalam kombinasi dengan informasi yang terkandung dalam entitas induk Animal,.

    Oleh karena itu, Animal_IDproperti di Cat, Dog, dll entitas adalah baik PK dan kembali FK ke Animalentitas.

  2. Bedakan antara jenis breed:

    Hanya karena dua properti memiliki nama yang sama tidak selalu berarti bahwa properti itu sama, bahkan jika nama yang sama menyiratkan hubungan seperti itu. Dalam hal ini, apa yang sebenarnya Anda miliki sebenarnya CatBreeddan DogBreedsebagai "tipe" terpisah

Catatan Awal

  1. SQL khusus untuk Microsoft SQL Server (yaitu T-SQL). Artinya, berhati-hatilah dengan tipe data karena mereka tidak sama di semua RDBMS. Sebagai contoh, saya menggunakan VARCHARtetapi jika Anda perlu menyimpan sesuatu di luar set ASCII standar, Anda harus benar-benar menggunakannya NVARCHAR.
  2. Bidang ID dari tabel "type" ( Race,, CatBreeddan DogBreed) tidak bertambah secara otomatis (yaitu IDENTITAS dalam hal T-SQL) karena mereka adalah konstanta aplikasi (yaitu mereka adalah bagian dari aplikasi) yang merupakan nilai pencarian statis di database dan direpresentasikan sebagai enums di C # (atau bahasa lainnya). Jika nilai ditambahkan, mereka ditambahkan dalam situasi terkontrol. Saya mencadangkan penggunaan bidang penambahan otomatis untuk data pengguna yang masuk melalui aplikasi.
  3. Konvensi penamaan yang saya gunakan adalah memberi nama setiap tabel subclass dimulai dengan nama kelas utama diikuti oleh nama subclass. Ini membantu mengatur tabel serta menunjukkan dengan jelas (tanpa melihat FK) hubungan tabel subkelas dengan tabel entitas utama.
  4. Silakan lihat bagian "Edit Terakhir" di bagian akhir untuk catatan tentang Tampilan.

"Breed" sebagai "Race" -Pendekatan Khusus

Breed As Diagram khusus ras
Kumpulan tabel pertama ini adalah tabel lookup / types:

CREATE TABLE Race
(
  RaceID INT NOT NULL PRIMARY KEY
  RaceName VARCHAR(50) NOT NULL
);

CREATE TABLE CatBreed
(
  CatBreedID INT NOT NULL PRIMARY KEY,
  BreedName VARCHAR(50),
  CatBreedAttribute1 INT,
  CatBreedAttribute2 VARCHAR(10)
  -- other "CatBreed"-specific properties as needed
);

CREATE TABLE DogBreed
(
  DogBreedID INT NOT NULL PRIMARY KEY,
  BreedName VARCHAR(50),
  DogBreedAttribute1 TINYINT
  -- other "DogBreed"-specific properties as needed
);

Daftar kedua ini adalah entitas "Hewan" utama:

CREATE TABLE Animal
(
  AnimalID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race
  Name VARCHAR(50)
  -- other "Animal" properties that are shared across "Race" types
);

ALTER TABLE Animal
  ADD CONSTRAINT [FK_Animal_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

Seperangkat tabel ketiga ini adalah entitas sub-kelas gratis yang melengkapi definisi masing Race- masing Animal:

CREATE TABLE AnimalCat
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  CatBreedID INT NOT NULL, -- FK to CatBreed
  HairColor VARCHAR(50) NOT NULL
  -- other "Cat"-specific properties as needed
);

ALTER TABLE AnimalCat
  ADD CONSTRAINT [FK_AnimalCat_CatBreed]
  FOREIGN KEY (CatBreedID)
  REFERENCES CatBreed (CatBreedID);

ALTER TABLE AnimalCat
  ADD CONSTRAINT [FK_AnimalCat_Animal]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal (AnimalID);


CREATE TABLE AnimalDog
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  DogBreedID INT NOT NULL, -- FK to DogBreed
  HairColor VARCHAR(50) NOT NULL
  -- other "Dog"-specific properties as needed
);

ALTER TABLE AnimalDog
  ADD CONSTRAINT [FK_AnimalDog_DogBreed]
  FOREIGN KEY (DogBreedID)
  REFERENCES DogBreed (DogBreedID);

ALTER TABLE AnimalDog
  ADD CONSTRAINT [FK_AnimalDog_Animal]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal (AnimalID);

Model menggunakan breedtipe bersama ditampilkan setelah bagian "Catatan Tambahan".

catatan tambahan

  1. Konsep breedtampaknya menjadi titik fokus untuk kebingungan. Itu disarankan oleh jcolebrand (dalam komentar pada pertanyaan) yang breedmerupakan properti yang dibagikan di antara yang berbeda race, dan dua jawaban lainnya memilikinya terintegrasi seperti dalam model mereka. Namun, ini merupakan kesalahan, karena nilai untuk breedtidak dibagi di antara nilai yang berbeda dari race. Ya, saya menyadari bahwa dua model lain yang diusulkan berupaya menyelesaikan masalah ini dengan menjadikannya racesebagai induk breed. Sementara itu secara teknis memecahkan masalah hubungan, itu tidak membantu memecahkan pertanyaan pemodelan keseluruhan tentang apa yang harus dilakukan tentang properti yang tidak umum, atau bagaimana menangani raceyang tidak memiliki a breed. Tapi, dalam hal properti seperti itu dijamin ada di semuaAnimals, saya akan menyertakan opsi untuk itu juga (di bawah).
  2. Model yang diusulkan oleh vijayp dan DavidN (yang tampaknya identik) tidak berfungsi karena:
    1. Mereka juga
      1. jangan izinkan properti non-umum disimpan (setidaknya tidak untuk masing-masing instance Animal), atau
      2. mengharuskan semua properti untuk semua racedisimpan dalam Animalentitas yang merupakan cara yang sangat datar (dan hampir non-relasional) untuk mewakili data ini. Ya, orang melakukan ini sepanjang waktu, tetapi itu artinya memiliki banyak bidang NULL per baris untuk properti yang tidak dimaksudkan untuk bidang tertentu tersebut raceDAN mengetahui bidang mana per baris yang terkait dengan catatan tertentu race.
    2. Mereka tidak memungkinkan untuk menambahkan racedari Animaldalam waktu yang tidak memiliki breedsebagai properti. Dan bahkan jika SEMUA Animalmemiliki breed, itu tidak akan mengubah struktur karena apa yang telah dicatat sebelumnya breed: yang breedbergantung pada race(yaitu breeduntuk Catbukan hal yang sama seperti breeduntuk Dog).

"Breed" sebagai Pendekatan Properti Bersama / Bersama

masukkan deskripsi gambar di sini
Tolong dicatat:

  1. SQL di bawah ini dapat dijalankan dalam database yang sama dengan model yang disajikan di atas:

    1. The Racemeja adalah sama
    2. The Breedtabel baru
    3. Tiga Animaltabel telah ditambahkan dengan2
  2. Bahkan dengan Breedmenjadi properti yang sekarang umum, tampaknya tidak benar untuk tidak Racemencatat dalam entitas induk / induk (meskipun secara teknis benar secara relasional). Jadi, keduanya RaceIDdan BreedIDdiwakili dalam Animal2. Untuk mencegah ketidaksesuaian antara yang RaceIDdicatat dalam Animal2dan BreedIDyang berbeda RaceID, saya telah menambahkan FK pada keduanya RaceID, BreedIDyang merujuk KONSTRA UNIK dari bidang-bidang dalam Breedtabel. Saya biasanya membenci menunjuk seorang FK ke CONSTRAINT UNIK, tetapi di sini adalah salah satu dari beberapa alasan yang sah untuk melakukannya. KONSTRA UNIK secara logis merupakan "Kunci Alternatif", yang membuatnya valid untuk penggunaan ini. Harap perhatikan juga bahwa Breedtabel masih memiliki PK hanya BreedID.
    1. Alasan untuk tidak pergi hanya dengan PK pada bidang gabungan dan tidak ada KONSTRA UNIK adalah bahwa hal itu akan memungkinkan hal yang sama BreedIDdiulang di berbagai nilai RaceID.
    2. Alasan untuk tidak beralih yang PK dan KONSTRA UNIK sekitar adalah bahwa ini mungkin bukan satu-satunya penggunaan BreedID, jadi masih mungkin untuk referensi nilai tertentu Breedtanpa memiliki yang RaceIDtersedia.
  3. Sementara model berikut ini berfungsi, ia memiliki dua kelemahan potensial terkait konsep shared Breed(dan itulah sebabnya saya lebih suka tabel Race-specific Breed).
    1. Ada asumsi implisit bahwa SEMUA nilai Breedmemiliki sifat yang sama. Tidak ada cara mudah dalam model ini untuk memiliki sifat yang berbeda antara Dog"breed" dan Elephant"breed". Namun, masih ada cara untuk melakukan ini, yang dicatat di bagian "Edit Akhir".
    2. Tidak ada cara untuk membagikan Breedlebih dari satu ras. Saya tidak yakin apakah itu diinginkan untuk dilakukan (atau mungkin tidak dalam konsep hewan tetapi mungkin dalam situasi lain yang akan menggunakan model jenis ini), tetapi tidak mungkin di sini.
CREATE TABLE Race
(
  RaceID INT NOT NULL PRIMARY KEY,
  RaceName VARCHAR(50) NOT NULL
);

CREATE TABLE Breed
(
  BreedID INT NOT NULL PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race
  BreedName VARCHAR(50)
);

ALTER TABLE Breed
  ADD CONSTRAINT [UQ_Breed]
  UNIQUE (RaceID, BreedID);

ALTER TABLE Breed
  ADD CONSTRAINT [FK_Breed_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

CREATE TABLE Animal2
(
  AnimalID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race, FK to Breed
  BreedID INT NOT NULL, -- FK to Breed
  Name VARCHAR(50)
  -- other properties common to all "Animal" types
);

ALTER TABLE Animal2
  ADD CONSTRAINT [FK_Animal2_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

-- This FK points to the UNIQUE CONSTRAINT on Breed, _not_ to the PK!
ALTER TABLE Animal2
  ADD CONSTRAINT [FK_Animal2_Breed]
  FOREIGN KEY (RaceID, BreedID)
  REFERENCES Breed (RaceID, BreedID);


CREATE TABLE AnimalCat2
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  HairColor VARCHAR(50) NOT NULL
);

ALTER TABLE AnimalCat2
  ADD CONSTRAINT [FK_AnimalCat2_Animal2]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal2 (AnimalID);

CREATE TABLE AnimalDog2
(
  AnimalID INT NOT NULL PRIMARY KEY,
  HairColor VARCHAR(50) NOT NULL
);

ALTER TABLE AnimalDog2
  ADD CONSTRAINT [FK_AnimalDog2_Animal2]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal2 (AnimalID);


Sunting Akhir (semoga ;-)

  1. Mengenai kemungkinan (dan kemudian kesulitan) menangani sifat yang berbeda antara jenis Breed, adalah mungkin untuk menggunakan konsep subclass / warisan yang sama tetapi dengan Breedsebagai entitas utama. Dalam pengaturan ini Breedtabel akan memiliki sifat-sifat yang umum untuk semua jenis Breed(seperti Animaltabel) dan RaceIDakan mewakili jenis Breed(sama seperti halnya dalam Animaltabel). Maka Anda akan memiliki tabel subclass seperti BreedCat, BreedDog, dan sebagainya. Untuk proyek yang lebih kecil ini mungkin dianggap "rekayasa berlebihan", tetapi sedang disebutkan sebagai pilihan untuk situasi yang akan mendapat manfaat dari itu.
  2. Untuk kedua pendekatan, terkadang membantu untuk membuat Tampilan sebagai jalan pintas ke entitas penuh. Sebagai contoh, pertimbangkan:

    CREATE VIEW Cats AS
       SELECT  an.AnimalID,
               an.RaceID,
               an.Name,
               -- other "Animal" properties that are shared across "Race" types
               cat.CatBreedID,
               cat.HairColor
               -- other "Cat"-specific properties as needed
       FROM    Animal an
       INNER JOIN  AnimalCat cat
               ON  cat.AnimalID = an.AnimalID
       -- maybe add in JOIN(s) and field(s) for "Race" and/or "Breed"
    
  3. Meskipun bukan bagian dari entitas logis, cukup umum untuk memiliki bidang audit dalam tabel untuk setidaknya memahami kapan catatan dimasukkan dan diperbarui. Jadi secara praktis:
    1. Sebuah CreatedDatelapangan akan ditambahkan ke Animalmeja. Bidang ini tidak diperlukan dalam tabel subkelas mana pun (misalnya AnimalCat) karena baris yang dimasukkan untuk kedua tabel harus dilakukan pada waktu yang sama dalam suatu transaksi.
    2. Sebuah LastModifiedDatelapangan akan ditambahkan ke Animalmeja dan semua tabel subclass. Bidang ini akan diperbarui hanya jika tabel tertentu diperbarui: jika pembaruan terjadi AnimalCattetapi tidak dalam Animaluntuk tertentu AnimalID, maka hanya LastModifiedDatebidang yang AnimalCatakan ditetapkan.
Solomon Rutzky
sumber
2
Entah bagaimana saya mendapatkan perasaan Anda mengerti persis apa masalah saya. Saya akan memberikan jawaban terkait Anda melihat, dan mempelajarinya dengan cermat. Hanya definisi sederhana dari tabel akan menjadi bagus juga (jika query SQL terlalu banyak untuk Anda tulis saat ini). Jika Anda memutuskan untuk memperbarui posting Anda dengan pertanyaan SQL atau definisi tabel, silakan beri saya komentar. Terima kasih lagi. Salam Hormat.
AlwaysLearningNewStuff
1
Saya mencoba menerapkan jawaban Anda pada kasus kehidupan nyata saya. Jika saya mengikuti instruksi Anda secara membabi buta, saya yakin saya akan kehilangan kesempatan untuk lebih mengoptimalkan desain saya. Saya ingin Anda melihat pertanyaan terakhir saya karena Anda telah dapat dengan sempurna memahami pertanyaan saya, dan memberikan jawaban yang sangat baik. Saya telah menyusun pertanyaan untuk menggunakan model data umum agar bermanfaat bagi pembaca di masa mendatang juga. Jika Anda kesulitan menemukannya, beri saya komentar. Terima kasih dan maaf sudah mengganggu ...
AlwaysLearningNewStuff
@AlwaysLearningNewStuff Hai. Dapatkan pesan ini lebih awal tetapi tidak punya waktu untuk langsung melakukannya. Saya dapat menemukan Pertanyaan baru dengan mengklik nama Anda di atas dan itu menunjukkan semua Pertanyaan Anda :-).
Solomon Rutzky
Saya merujuk pada pertanyaan ini . Singkatnya: Saya memiliki 3 entitas dengan atribut yang sama D, oleh karena itu saya ingin menerapkan metode dari jawaban Anda. Dua entitas memiliki atribut umum Eyang tidak ada pada entitas ketiga. Haruskah saya mengabaikan fakta ini dan menerapkan solusi standar, atau adakah cara untuk lebih mengoptimalkan desain saya?
AlwaysLearningNewStuff
4

Pertama, Anda melakukannya dengan baik untuk membedakan antara pemodelan ER dan pemodelan relasional. Banyak pemula tidak.

Berikut adalah beberapa kata kunci yang dapat Anda gunakan untuk mencari artikel bermanfaat di web.

Kasing Anda adalah kasing klasik kelas / subkelas atau, jika Anda suka, ketik / subtipe.

Ungkapan yang digunakan dalam pemodelan ER adalah "generalisasi / spesialisasi". Dan banyak artikel menunjukkan ini di bawah sesuatu yang disebut pemodelan EER (Enhanced Entity-Relationship). Ini bukan dalam presentasi asli pemodelan ER dari Peter Chen. Itu ditambahkan kemudian. Untuk ringkasan gen / spek yang cukup bagus dalam bentuk pdf, klik di sini

Selanjutnya, saat mengonversi case kelas / subclass ke pemodelan relasional Anda mendesain tabel. Ada lebih dari satu pendekatan. Dua pendekatan utama disebut pewarisan tabel tunggal dan warisan tabel kelas. Masing-masing memiliki kelebihan dan kekurangan. Presentasi terbaik dari kedua desain ini berasal dari Martin Fowler. Anda dapat melihat garis besarnya di sini dan di sini .

Keuntungan besar dari pewarisan tabel tunggal adalah kesederhanaan. Semuanya disimpan dalam satu tabel. Kerugian besar adalah banyak NULLS. Ini dapat membuang-buang ruang dan waktu dan menghasilkan logika yang membingungkan.

Warisan tabel kelas membutuhkan gabungan, tetapi sederhana dan cepat. Terutama jika Anda menggunakan teknik yang disebut kunci primer bersama, di mana PK dalam tabel subkelas adalah salinan PK dalam tabel superclass. Anda dapat membuat tampilan untuk setiap subclass yang bergabung dengan data superclass dengan data subclass.

Terakhir, ada tag di area ini yang mengumpulkan pertanyaan seperti pertanyaan Anda bersama.
Ini dia:

Walter Mitty
sumber
1
+1 Yang membingungkan saya adalah kurangnya kunci utama dalam diagram tabel. Terutama di "classTableInheritance" saya tidak bisa melihat bahwa semua tabel ini dihubungkan oleh kunci primer yang sama.
miracle173
@ miracle173 poin yang valid. Untuk beberapa alasan, Fowler tidak memasukkan PK dan FK dalam diagram. Ada artikel lain di bawah warisan tabel kelas yang memberikan detail ini. Tidak semua implementasi pewarisan tabel kelas menggabungkannya dengan kunci primer bersama. Saya merekomendasikannya. Ini sedikit lebih banyak bekerja pada waktu memasukkan, tetapi lebih mudah dan lebih cepat pada waktu pengambilan bergabung.
Walter Mitty
3

Saya melihat kemungkinan desain sebagai

Meja Race

RaceId- PK- Int
RaceName - Varchar(50)

Meja Breed

BreedId - PK- Int
RaceId - FK - Int
BreedName - varchar(50)

Meja Animal

AnimalId - PK- Int
BreedId - FK - Int
Other Columns....

PK ini di atas akan menjadi kolom penambahan otomatis. Kolom lain dalam Animaltabel dapat dinamai sesuai.

masukkan deskripsi gambar di sini

vijayp
sumber
Selain itu saya akan menambahkan bidang dengan kunci Ras dan Jenis (bisa menjadi pemicu) di tabel Animal untuk memfasilitasi indeks kemudian untuk meningkatkan kecepatan.
Felipe Alcacibar
0

Metode Anda saat ini tidak buruk. Namun, jika Anda akan menambahkan lebih banyak balapan nanti (burung, ikan, dll.) Maka membuat tabel terpisah untuk masing-masing bisa menjadi rumit. Saya akan merekomendasikan sesuatu seperti berikut:

Animal < # Animal_ID, Breed_ID, other attributes >
Breed < # Breed_ID, Race_ID >
Race < # Race_ID >

Seekor ras, menurut pemahaman saya, seharusnya hanya memiliki satu ras. Jadi, jika Anda menyimpan breed di tabel Animal Anda akan dapat menentukan ras dengan bergabung ke tabel Breed. Jelas, tambahkan atribut lain (nama, deskripsi, dll.) Ke tabel Breed dan Race sesuai kebutuhan.

DavidN
sumber