2011-10-14 34 views
7

Tôi đang xóa một hàng trong bảng trên một trang web có mối quan hệ nhiều-nhiều. Tôi cũng muốn xóa mọi hàng liên quan ở phía bên kia của mối quan hệ đó. Ví dụ, giả sử tôi có các bảng sau đây và tôi muốn xóa một hàng từ Cars. Tôi cũng muốn xóa mọi hàng có liên quan khỏi Drivers và, tất nhiên, mọi hàng không còn cần thiết trong CarDrivers.Xóa các hàng có liên quan trong mối quan hệ nhiều-nhiều-số

Table Cars: 
CarID  int 
CarName nvarchar(100) 

Table Drivers: 
DriverID int 
DriverName nvarchar(100) 

Table CarDrivers: 
CarID  int 
Driver  int 

Tôi biết cách tham gia các bảng ở trên trong truy vấn SELECT. Nhưng tôi không thấy cách xóa dữ liệu trong mối quan hệ.

Lưu ý: Cả hai bên của mối quan hệ đều thực hiện xóa tầng. Vì vậy, ví dụ: xóa một hàng khỏi Cars sẽ xóa mọi hàng có liên quan trong CarDrivers. Nhưng rõ ràng là không lan truyền đến bảng Drivers.

+0

bản sao có thể có của [Làm cách nào để xóa từ nhiều bảng bằng INNER JOIN trong máy chủ SQL] (http://stackoverflow.com/questions/783726/how-do-i-delete-from-multiple-tables-using- inner-join-in-sql-server) –

+1

@OMG Ponies: không đồng ý, nó không phải là một chuỗi bị xóa vì CarDrivers to Drivers sẽ là một đứa trẻ đang xóa một phụ huynh. Cha mẹ có thể có những đứa con khác. Xem câu trả lời của tôi xin vui lòng – gbn

+0

-1 cho câu hỏi gây hiểu lầm và không đầy đủ với một ví dụ xấu – gbn

Trả lời

5

Tôi nghĩ cách tiếp cận tốt nhất là bạn sẽ phải xóa dữ liệu của bảng có liên quan trước. Nói cách khác, nếu bạn muốn xóa một chiếc xe và các trình điều khiển tương ứng sử dụng chiếc xe đó, bạn phải xóa các trình điều khiển đầu tiên, và sau đó là xe. Bảng kết hợp sẽ xóa các bản ghi chính xác vì ON CASCADE DELETE.

Hãy thử điều này:

delete 
from Drivers 
where DriverID in 
(
    select d.DriverID 
    from Drivers d 
    inner join CarDrivers cd 
    on d.DriverID = cd.Driver 
    inner join Cars c 
    on c.CarID = cd.CarID 
    where c.CarID = 1 
) 

delete 
from Cars 
where CarID = 1 

Đương nhiên, bạn không cần phải hardcode 1 đó, bạn có thể sử dụng bất cứ điều gì kể cả một tham số nếu bạn đang sử dụng đoạn mã này trong proc lưu trữ.

0

Đặt xóa tầng trên bảng CarDrivers.

+0

Điều đó sẽ chỉ xóa dữ liệu liên quan trong bảng CarDrivers. Tôi tin rằng OP cũng muốn xóa dữ liệu bảng tương ứng là một phần của việc tham gia. Trong trường hợp này, việc xóa tầng sẽ không đáp ứng được nhu cầu. –

0

Nếu bạn có quyền truy cập vào cơ sở dữ liệu và có quyền thay đổi các bảng, tôi sẽ chỉ tạo ra các phím nước ngoài và chỉ định onupdate và oncascade như vậy:

ALTER TABLE [dbo].[Drivers] WITH CHECK ADD CONSTRAINT [FK__Cars] FOREIGN KEY([CarID]) 
REFERENCES [dbo].[Car] ([CarID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 

ALTER TABLE [dbo].[CarDrivers] WITH CHECK ADD CONSTRAINT [FK_Drivers_Cars] FOREIGN KEY([CarID]) 
REFERENCES [dbo].[Car] ([CarID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 

Lợi ích của phương pháp này là bạn không cần phải lo lắng về các hồ sơ trẻ mồ côi. Thời điểm bạn xóa một bản ghi khỏi bảng Ô tô, tất cả các liên quan trong các bảng khác sẽ tự động bị xóa và cập nhật. Các câu lệnh SQL của bạn cũng ngắn hơn.

1

Yêu cầu của bạn không có ý nghĩa

Trình điều khiển dưới dạng thực thể tồn tại riêng biệt với Ô tô. Ô tô có thể được điều khiển bởi nhiều tài xế, người lái xe có thể lái nhiều ô tô. Đây là lý do tại sao bạn có nhiều bảng.

Lưu ý rằng "trình điều khiển có thể mang nhiều ô tô" bit. Điều này có nghĩa là nếu bạn xóa hàng Trình điều khiển, bạn cần xóa các hàng khác trong CarDrivers.

Nếu bạn vẫn còn muốn thực hiện việc này, bạn cần kích hoạt trên CarDrivers. CASCADE từ Drivers đến CarDrivers sẽ xóa các hàng CarDrivers khác cho bạn. Không thể nhớ hành vi mặc định cho đệ quy kích hoạt quá.

Thật là một mớ hỗn độn.

Lưu ý: điều này gần như có ý nghĩa nếu bạn có duy nhất trên một trong các cột trong bảng nhiều, sau đó nó phải là khóa ngoài giữa Ô tô và Trình điều khiển (Duy nhất trên xe có nghĩa là "nhiều nhất một trình điều khiển cho mỗi ô tô "có nghĩa là cột FK NULLable trong Ô tô)

+0

Bảng điều khiển ô tô, tài xế và xe hơi là một ví dụ để minh họa những gì tôi đang cố gắng làm. Đây là ứng dụng tôi đang làm việc. Tôi sẽ xem xét thiết kế theo những cách bạn mô tả, nhưng có thể không tùy thuộc vào tôi để thay đổi thiết kế. Tôi nghĩ rằng nó có một cái gì đó để làm với thực tế là một trong những bảng được liên kết với các bảng khác và bảng giao nhau chứa một vài trường bổ sung. –

+0

@Jonathan Wood: thiết kế là âm thanh nếu bạn cần nhiều bàn. Đó là yêu cầu không rõ ràng – gbn

+0

Nhìn vào nó hơn nữa, có vẻ như đó là mối quan hệ một-nhiều; tuy nhiên, một bảng nối được sử dụng chủ yếu vì những lý do tôi vạch ra. Tôi có thể đảm bảo với bạn rằng nó không có ý nghĩa để lại các mục mồ côi ở phía bên kia của mối quan hệ. –

0

Không có mối quan hệ nào giữa bảng điều khiển và ô tô. Mối quan hệ này là thông qua bảng CarDrivers. Do đó, vấn đề vẫn tồn tại. Cách duy nhất tôi biết để tự động xóa CASCADE là xóa FK giữa bảng CarDrivers và Drivers và thêm một kích hoạt trước hoặc sau khi xóa để CarDrivers xóa mục nhập trong trình điều khiển nơi driver_id là một trong các hàng đang được đã xóa trong CarDrivers.

Điều này không sạch sẽ theo nhiều cách. Nếu việc xóa thực sự được yêu cầu trên bảng kết nối, thì mối quan hệ có thể được mô hình sai và mối quan hệ rõ ràng hơn sẽ là mô hình hóa mối quan hệ đơn giản là 'có nhiều người lái xe' hoặc FK Ô tô trong bảng Trình điều khiển . Như đã nói ở trên, đối với những chiếc ô tô và tài xế thực tế, mối quan hệ nhiều-nhiều sẽ thực sự chính xác và bạn sẽ không bao giờ xóa một tài xế chỉ vì chiếc xe đã được tổng cộng/xóa.

Các vấn đề liên quan