Apakah akan dianggap sebagai praktik buruk untuk memiliki beberapa FK yang dapat dibatalkan pada tabel di SQL Server

13

Pada struktur database saya di SQL Server, saya memiliki 3 jenis produk yang memerlukan informasi berbeda tentang pesanan. Jadi, saya membuat satu Customersmeja dan tiga perintah tabel yang berbeda: OrdersForProductAs, OrdersForProductBs, OrdersForProductCs. Semua tabel pesanan memiliki satu hingga banyak hubungan di atas Customersmeja.

Saya juga punya meja lain yaitu Paymentsdan akan menyimpan rincian pembayaran di dalamnya. Tapi saya ragu di sini tentang cara menyusunnya.

Karena saya memiliki beberapa jenis produk dan pelanggan mungkin memiliki pesanan untuk beberapa produk secara bersamaan, saya perlu menghubungkan ketiga tabel pesanan ke Paymentstabel.

Masalah lainnya adalah bahwa pelanggan mungkin memiliki pesanan hanya untuk satu jenis produk. Jadi, kolom FK pada Paymentstabel perlu nullable.

Pertanyaan saya adalah apakah nullablekolom-kolom FK itu akan menjadi sakit kepala bagi saya dalam jangka panjang atau tidak? Secara umum, akankah dianggap sebagai praktik yang buruk untuk memiliki kolom FK yang dapat dibatalkan pada tabel?

tugberk
sumber
2
Pastikan Anda menyertakan batasan pemeriksaan sehingga setidaknya salah satu dari FK tersebut tidak nol.
Damien_The_Unbeliever
3
Satu kunci asing yang dapat dibatalkan adalah satu terlalu banyak.
nvogel

Jawaban:

13

Saya akan mempertanyakan mengapa Anda memiliki OrdersForProductXtabel sama sekali.
Mungkin masalah FK yang Anda tanyakan dapat dirancang ...

Jika tabel ini memiliki struktur yang sama, maka Anda hanya perlu ProductTypekolom pada beberapa OrderProducttabel. KemudianPayment hanya tautan ke sana dengan satu FK

Jika tabel memiliki struktur yang berbeda, saya berasumsi mereka memiliki beberapa atribut yang sama. Jadi, Anda dapat memiliki OrderProducttabel umum kemudian tabel anak spesifik per jenis produk (lihat di bawah) Sekali lagi, Paymenttautkan ke tabel commone dengan satu FK

Ini adalah "pola superkey / subtipe"

  • UQ1 adalah "kunci super" yang digunakan kunci asing pada tabel subtipe
  • Setiap tabel subtipe memiliki gabungan PK dan FK (OrderID, ProductType)
  • Setiap tabel subtipe memiliki kendala PERIKSA untuk membatasi jenis dalam tabel itu

Memesan produk

  • OrderID, PK, UQ1
  • Jenis Produk, UQ1
  • CommonThing1
  • ...

PesanProdukA

  • OrderID, PK, FK
  • ProductType, PK, FK, PERIKSA ProductType = A
  • ProdukAThing1
  • ...

PesanProdukB

  • OrderID, PK, FK
  • ProductType, PK, FK, PERIKSA ProductType = B
  • ProductBThing1
  • ...
gbn
sumber
4
@tugberk: Perhatikan bahwa Anda tidak akan memiliki NULLkolom FK dengan pendekatan ini.
ypercubeᵀᴹ
"Jika tabel ini memiliki struktur yang sama" Mereka tidak memiliki struktur yang sama.
tugberk
5

Hindari "kunci asing" yang tidak dapat dibatalkan. Mereka memiliki banyak kelemahan.

Batasan pada baris referensi tidak selalu ditegakkan ketika kunci asing berisi nol. Namun, perilaku default itu tidak konsisten antara DBMS yang berbeda. Beberapa DBMS mendukung opsi konfigurasi untuk mengubah perilaku kunci asing yang dapat dibatalkan dan beberapa tidak. Oleh karena itu, pengembang dan pengguna SQL mungkin tidak jelas tentang apa arti batasan kunci asing yang dapat dibatalkan dari perspektif integritas data. Porting database antara produk DBMS atau bahkan antara server yang berbeda menggunakan produk yang sama dapat memberikan hasil yang tidak konsisten.

Alat desain basis data, alat integrasi, dan perangkat lunak lain tidak selalu mendukungnya dengan benar dan hasil yang mereka hasilkan mungkin salah.

Kunci asing sering digunakan dalam gabungan dan logika kueri lainnya, memperparah masalah bagi pengguna yang berpikir kendala berlaku ketika tidak atau yang tidak tahu logika yang diterapkan oleh DBMS khusus Anda.

Beberapa fitur pengoptimalan kueri yang memungkinkan penulisan ulang kueri dan pengoptimalan lainnya mungkin tidak tersedia ketika kunci asing dibatalkan.

Dalam istilah logis, batasan "kunci asing" yang tidak dapat dibatalkan tidak masuk akal secara logis. Menurut standar SQL kendala seperti itu mungkin tidak dilanggar bahkan jika tabel yang direferensikan kosong. Itu bertentangan dengan salah satu justifikasi dugaan paling umum untuk menggunakan null - yang mewakili kasus "tidak diketahui". Jika tidak ada nilai X yang valid maka X "tidak dikenal" pasti tidak bisa menjadi nilai yang valid - dan SQL akan mengizinkannya.

Kunci asing yang dapat dibatalkan tidak perlu sama sekali. Anda selalu bisa menguraikan kunci asing ke tabel baru atau menggunakan pola supertipe / subtipe sehingga nol tidak diperlukan. Demi kesederhanaan dan akurasi, lebih baik meninggalkan nol daripada memasukkannya.

nvogel
sumber
2

Saya belum pernah mendengar itu dianggap praktik buruk untuk menggunakan kolom FK yang dapat dibatalkan. Mereka sangat cocok untuk kolom yang mereferensikan tabel lain tetapi mungkin tidak diisi (yaitu data opsional).

(Mengapa menurut Anda itu akan menjadi masalah?)

StilesCrisis
sumber
Terima kasih! Yah, saya tidak begitu yakin tentang itu tetapi saya punya proyek seperti itu beberapa tahun yang lalu dan saya ingat bahwa saya mengalami sakit kepala pada sesuatu . Jadi, saya tidak jelas seperti yang Anda lihat: itulah mengapa saya mengajukan pertanyaan.