Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bagaimana Anda bisa mewakili warisan dalam database?

@Bill Karwin menjelaskan tiga model pewarisan dalam buku SQL Antipatterns-nya, ketika mengusulkan solusi untuk antipattern SQL Entity-Attribute-Value. Ini adalah gambaran singkatnya:

Pewarisan Tabel Tunggal (alias Pewarisan Tabel Per Hierarki):

Menggunakan satu tabel seperti pada opsi pertama Anda mungkin merupakan desain yang paling sederhana. Seperti yang Anda sebutkan, banyak atribut yang spesifik untuk subtipe harus diberi NULL nilai pada baris di mana atribut ini tidak berlaku. Dengan model ini, Anda akan memiliki satu tabel kebijakan, yang akan terlihat seperti ini:

+------+---------------------+----------+----------------+------------------+
| id   | date_issued         | type     | vehicle_reg_no | property_address |
+------+---------------------+----------+----------------+------------------+
|    1 | 2010-08-20 12:00:00 | MOTOR    | 01-A-04004     | NULL             |
|    2 | 2010-08-20 13:00:00 | MOTOR    | 02-B-01010     | NULL             |
|    3 | 2010-08-20 14:00:00 | PROPERTY | NULL           | Oxford Street    |
|    4 | 2010-08-20 15:00:00 | MOTOR    | 03-C-02020     | NULL             |
+------+---------------------+----------+----------------+------------------+

\------ COMMON FIELDS -------/          \----- SUBTYPE SPECIFIC FIELDS -----/

Menjaga desain tetap sederhana adalah nilai tambah, tetapi masalah utama dengan pendekatan ini adalah sebagai berikut:

  • Saat menambahkan subtipe baru, Anda harus mengubah tabel untuk mengakomodasi atribut yang menjelaskan objek baru ini. Ini dapat dengan cepat menjadi masalah jika Anda memiliki banyak subtipe, atau jika Anda berencana untuk menambahkan subtipe secara teratur.

  • Basis data tidak akan dapat menerapkan atribut mana yang berlaku dan mana yang tidak, karena tidak ada metadata untuk menentukan atribut mana yang termasuk dalam subtipe mana.

  • Anda juga tidak dapat menerapkan NOT NULL pada atribut subtipe yang harus wajib. Anda harus menangani ini di aplikasi Anda, yang secara umum tidak ideal.

Warisan Meja Beton:

Pendekatan lain untuk mengatasi pewarisan adalah dengan membuat tabel baru untuk setiap subtipe, mengulangi semua atribut umum di setiap tabel. Misalnya:

--// Table: policies_motor
+------+---------------------+----------------+
| id   | date_issued         | vehicle_reg_no |
+------+---------------------+----------------+
|    1 | 2010-08-20 12:00:00 | 01-A-04004     |
|    2 | 2010-08-20 13:00:00 | 02-B-01010     |
|    3 | 2010-08-20 15:00:00 | 03-C-02020     |
+------+---------------------+----------------+
                          
--// Table: policies_property    
+------+---------------------+------------------+
| id   | date_issued         | property_address |
+------+---------------------+------------------+
|    1 | 2010-08-20 14:00:00 | Oxford Street    |   
+------+---------------------+------------------+

Desain ini pada dasarnya akan memecahkan masalah yang diidentifikasi untuk metode tabel tunggal:

  • Atribut wajib sekarang dapat diterapkan dengan NOT NULL .

  • Menambahkan subtipe baru memerlukan penambahan tabel baru alih-alih menambahkan kolom ke yang sudah ada.

  • Juga tidak ada risiko bahwa atribut yang tidak pantas disetel untuk subtipe tertentu, seperti vehicle_reg_no bidang untuk kebijakan properti.

  • Tidak perlu type atribut seperti dalam metode tabel tunggal. Jenisnya sekarang ditentukan oleh metadata:nama tabel.

Namun model ini juga memiliki beberapa kelemahan:

  • Atribut umum dicampur dengan atribut khusus subtipe, dan tidak ada cara mudah untuk mengidentifikasinya. Basis data juga tidak akan tahu.

  • Saat mendefinisikan tabel, Anda harus mengulangi atribut umum untuk setiap tabel subtipe. Itu jelas bukan KERING.

  • Mencari semua kebijakan terlepas dari subtipe menjadi sulit, dan akan membutuhkan banyak UNION s.

Ini adalah bagaimana Anda harus menanyakan semua kebijakan terlepas dari jenisnya:

SELECT     date_issued, other_common_fields, 'MOTOR' AS type
FROM       policies_motor
UNION ALL
SELECT     date_issued, other_common_fields, 'PROPERTY' AS type
FROM       policies_property;

Perhatikan bagaimana menambahkan subtipe baru akan memerlukan permintaan di atas untuk dimodifikasi dengan tambahan UNION ALL untuk setiap subtipe. Ini dapat dengan mudah menyebabkan bug di aplikasi Anda jika operasi ini dilupakan.

Pewarisan Tabel Kelas (alias Warisan Tabel Per Jenis):

Ini adalah solusi yang @David sebutkan di jawaban lain. Anda membuat satu tabel untuk kelas dasar Anda, yang mencakup semua atribut umum. Kemudian Anda akan membuat tabel khusus untuk setiap subtipe, yang kunci utamanya juga berfungsi sebagai kunci asing ke tabel dasar. Contoh:

CREATE TABLE policies (
   policy_id          int,
   date_issued        datetime,

   -- // other common attributes ...
);

CREATE TABLE policy_motor (
    policy_id         int,
    vehicle_reg_no    varchar(20),

   -- // other attributes specific to motor insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

CREATE TABLE policy_property (
    policy_id         int,
    property_address  varchar(20),

   -- // other attributes specific to property insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

Solusi ini memecahkan masalah yang diidentifikasi dalam dua desain lainnya:

  • Atribut wajib dapat diterapkan dengan NOT NULL .

  • Menambahkan subtipe baru memerlukan penambahan tabel baru alih-alih menambahkan kolom ke yang sudah ada.

  • Tidak ada risiko bahwa atribut yang tidak pantas disetel untuk subtipe tertentu.

  • Tidak perlu type atribut.

  • Sekarang atribut umum tidak lagi dicampur dengan atribut khusus subtipe.

  • Kita bisa tetap KERING, akhirnya. Tidak perlu mengulang atribut umum untuk setiap tabel subtipe saat membuat tabel.

  • Mengelola id yang bertambah secara otomatis untuk kebijakan menjadi lebih mudah, karena ini dapat ditangani oleh tabel dasar, daripada setiap tabel subtipe yang membuatnya secara mandiri.

  • Mencari semua kebijakan terlepas dari subtipe sekarang menjadi sangat mudah:Tidak ada UNION s diperlukan - hanya SELECT * FROM policies .

Saya menganggap pendekatan tabel kelas sebagai yang paling cocok di sebagian besar situasi.

Nama ketiga model ini berasal dari buku Martin Fowler Patterns of Enterprise Application Architecture.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tidak dapat memotong tabel karena direferensikan oleh batasan KUNCI ASING - Tutorial SQL Server / TSQL Bagian 70

  2. Hirarki Teknologi Memori/Penyimpanan dan SQL Server

  3. Membuat, tidak merusak, kinerja SQL Server

  4. Wawasan tentang Batasan Unik SQL Server

  5. Cara mendapatkan koneksi String dari database