Bagaimana cara saya memodelkan hubungan nol atau satu ke nol atau satu di Sql Server dengan cara yang paling alami?
Ada tabel 'Bahaya' yang mencantumkan bahaya di situs. Ada tabel 'Tugas' untuk pekerjaan yang perlu dilakukan di situs. Beberapa Tugas adalah untuk memperbaiki bahaya, tidak ada tugas yang dapat menangani beberapa bahaya. Beberapa Bahaya memiliki tugas untuk memperbaikinya. Tidak ada bahaya yang dapat memiliki dua tugas yang terkait dengannya.
Di bawah ini adalah yang terbaik yang bisa saya pikirkan:
CREATE TABLE [dbo].[Hazard](
[HazardId] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Hazard] PRIMARY KEY CLUSTERED
(
[HazardId] ASC
))
GO
ALTER TABLE [dbo].[Hazard] WITH CHECK ADD CONSTRAINT [FK_Hazard_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([TaskId])
GO
CREATE TABLE [dbo].[Task](
[TaskId] [int] IDENTITY(1,1) NOT NULL,
[HazardId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED
(
[TaskId] ASC
))
GO
ALTER TABLE [dbo].[Task] WITH CHECK ADD CONSTRAINT [FK_Task_Hazard] FOREIGN KEY([HazardId])
REFERENCES [dbo].[Hazard] ([HazardId])
GO
Apakah Anda akan melakukannya secara berbeda? Alasan saya tidak senang dengan pengaturan ini adalah bahwa harus ada logika aplikasi untuk memastikan bahwa tugas dan bahaya menunjuk satu sama lain dan tidak ke tugas dan bahaya lain dan bahwa tidak ada tugas / bahaya menunjuk ke bahaya / tugas yang sama tugas / bahaya lain menunjuk ke.
Apakah ada cara yang lebih baik?
sumber
null
.CREATE UNIQUE INDEX x ON dbo.Hazards(TaskID) WHERE TaskID IS NOT NULL;
Jawaban:
Anda dapat menggunakan ide Anda sendiri tentang skema asimetris dengan menghapus salah satu kunci asing dari pengaturan saat ini, atau, untuk menjaga agar semuanya simetris, Anda dapat menghapus kedua kunci asing dan memperkenalkan tabel persimpangan dengan kendala unik pada setiap referensi .
Jadi, akan seperti ini:
Anda juga bisa mendeklarasikan
(HazardId, TaskId)
sebagai kunci utama jika Anda perlu referensi kombinasi ini dari tabel lain. Untuk tujuan menjaga pasangan tetap unik, kunci primer tidak diperlukan, cukup setiap ID unik.sumber
(HazardId, TaskId)
memiliki tuple(HazardId)
dan(TaskId)
keduanya mengidentifikasi deretan tabel ini secara unik. Salah satunya harus dipilih sebagai kunci utama.Untuk menyimpulkan:
Jika tabel Tugas dan Bahaya digunakan untuk hal lain (yaitu tugas dan / atau bahaya memiliki data lain yang terkait, dan model yang Anda perlihatkan kepada kami disederhanakan untuk hanya menampilkan bidang yang relevan) Saya akan mengatakan bahwa solusi Anda sudah benar.
Jika tidak, jika Tugas dan Bahaya hanya ada untuk digabungkan satu sama lain, Anda tidak perlu dua tabel; Anda bisa membuat tabel tunggal untuk hubungan mereka, dengan bidang-bidang berikut:
sumber
TaskID
danHazardID
? Anda bisa memiliki 2 kolom BITIsTask
,,IsHazard
dan batasan yang tidak keduanya salah. MakaHazard
tabel hanyalah sebuah tampilan:CRAETE VIEW Hazard SELECT HazardID = ID, HazardDetails, ... FROM ThisTable WHERE IsHazard = 1;
dan Tugas masing-masing.Pendekatan lain yang tampaknya belum disebutkan adalah memiliki Bahaya dan Tugas menggunakan ruang ID yang sama. Jika Hazard memiliki Tugas, ia akan memiliki ID yang sama. Jika suatu Tugas adalah untuk suatu Bahaya itu akan memiliki ID yang sama.
Anda akan menggunakan urutan daripada kolom identitas untuk mengisi ID ini.
Kueri pada model data jenis ini akan menggunakan gabungan luar (penuh) untuk mengambil hasilnya.
Pendekatan ini sangat mirip dengan jawaban @ AndriyM kecuali jawabannya memungkinkan ID berbeda, dan sebuah tabel untuk menyimpan hubungan ini.
Saya tidak yakin Anda ingin menggunakan pendekatan ini untuk skenario dua-tabel, tetapi itu bekerja dengan baik ketika jumlah tabel yang terlibat meningkat.
sumber