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

Cara membuat banyak satu ke satu

Anda menggunakan pewarisan (juga dikenal dalam pemodelan hubungan entitas sebagai "subkelas" atau "kategori"). Secara umum, ada 3 cara untuk merepresentasikannya dalam database:

  1. "Semua kelas dalam satu tabel": Miliki hanya satu tabel "mencakup" kelas induk dan semua anak (yaitu dengan semua kolom induk dan anak), dengan batasan CHECK untuk memastikan subset bidang yang tepat adalah non-NULL (yaitu dua anak yang berbeda tidak "bercampur").
  2. "Kelas beton per tabel": Memiliki tabel yang berbeda untuk setiap anak, tetapi tidak ada tabel induk. Ini membutuhkan hubungan orang tua (dalam kasus Anda Inventaris <- Penyimpanan) untuk diulang di semua anak.
  3. "Kelas per tabel": Memiliki tabel induk dan tabel terpisah untuk setiap anak, itulah yang Anda coba lakukan. Ini paling bersih, tetapi dapat menghabiskan beberapa kinerja (kebanyakan saat memodifikasi data, tidak terlalu banyak saat membuat kueri karena Anda dapat bergabung langsung dari turunan dan melewati induk).

Saya biasanya lebih suka pendekatan ke-3, tetapi terapkan keduanya keberadaan dan eksklusivitas seorang anak di tingkat aplikasi. Menerapkan keduanya di tingkat basis data agak rumit, tetapi dapat dilakukan jika DBMS mendukung kendala yang ditangguhkan. Misalnya:

CHECK (
    (
        (VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
        AND WAREHOUSE_ID IS NULL
    )
    OR (
        VAN_ID IS NULL
        AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
    )
)

Ini akan menegakkan kedua eksklusivitas (karena CHECK ) dan kehadiran (karena kombinasi CHECK dan FK1 /FK2 ) dari anak tersebut.

Sayangnya, MS SQL Server tidak mendukung batasan yang ditangguhkan, tetapi Anda mungkin dapat "menyembunyikan" seluruh operasi di balik prosedur tersimpan dan melarang klien memodifikasi tabel secara langsung.

Hanya eksklusivitas yang dapat diterapkan tanpa batasan yang ditangguhkan:

STORAGE_TYPE adalah jenis diskriminator, biasanya bilangan bulat untuk menghemat ruang (dalam contoh di atas, 0 dan 1 "diketahui" oleh aplikasi Anda dan diinterpretasikan sesuai dengan itu).

VAN.STORAGE_TYPE dan WAREHOUSE.STORAGE_TYPE dapat dihitung (alias. "dihitung") kolom untuk menghemat penyimpanan dan menghindari kebutuhan untuk CHECK s.

--- EDIT ---

Kolom yang dihitung akan bekerja di bawah SQL Server seperti ini:

CREATE TABLE STORAGE (
    STORAGE_ID int PRIMARY KEY,
    STORAGE_TYPE tinyint NOT NULL,
    UNIQUE (STORAGE_ID, STORAGE_TYPE)
);

CREATE TABLE VAN (
    STORAGE_ID int PRIMARY KEY,
    STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
    FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);

CREATE TABLE WAREHOUSE (
    STORAGE_ID int PRIMARY KEY,
    STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
    FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);

-- We can make a new van.
INSERT INTO STORAGE VALUES (100, 0);
INSERT INTO VAN VALUES (100);

-- But we cannot make it a warehouse too.
INSERT INTO WAREHOUSE VALUES (100);
-- Msg 547, Level 16, State 0, Line 24
-- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".

Sayangnya, SQL Server memerlukan kolom yang dihitung yang digunakan dalam bahasa asing kunci untuk BERTAHAN. Basis data lain mungkin tidak memiliki batasan ini (misalnya kolom virtual Oracle), yang dapat menghemat beberapa ruang penyimpanan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menjalankan paket SSIS dari .NET?

  2. Nilai desimal dalam SQL untuk membagi hasil

  3. Pernyataan Hapus SQL Server:Cara Menghapus Satu atau Mengalikan Baris dari Tabel

  4. Parameter Sniffing (atau Spoofing) di SQL Server

  5. SQL Server BIT Datatype – Panduan Utama