2011-10-06 117 views
4

我有兩個表,Cars和Drivers,通過第三個表CarDrivers以多對多的關係連接。更新多個多對多關係

我的用戶界面允許用戶檢查與當前車相關的任意數量的司機。每次檢查都指示應將一行輸入到CarDrivers表中。

我的問題是:當用戶提交表單時更新這些行的最有效方法是什麼?

我需要通過併爲CarDrivers添加一行,以檢查每個項目,併爲每個未選中項目刪除一個,同時保留那些未更改的項目。

我看到的唯一方法是逐個檢查每個組合,並添加那些不存在或刪除那些需要刪除的組合。有沒有一種輕鬆的方式?

我可以使用實體框架4,ADO.NET,直接SQL查詢或存儲過程。

回答

4

這正是MERGE語法發明的場景,特別是WHEN NOT MATCHED BY SOURCE條款。

一般來說,將當前狀態值放入暫存表中,然後使用MERGE來處理INSERTDELETE一次命中的操作。

這裏有一個簡短的素描:

CREATE TABLE Cars (VIN INTEGER NOT NULL UNIQUE); 

CREATE TABLE Drivers (driver_licence_number INTEGER NOT NULL UNIQUE); 

CREATE TABLE CarDrivers 
(
VIN INTEGER NOT NULL REFERENCES Cars (VIN), 
driver_licence_number INTEGER NOT NULL 
    REFERENCES Drivers (driver_licence_number) 
); 

INSERT INTO Cars VALUES (1), (2), (3); 
INSERT INTO Drivers VALUES (22), (55), (99); 

INSERT INTO CarDrivers VALUES (1, 22), (1, 55); 

CREATE TABLE CarDrivers_staging 
(
VIN INTEGER NOT NULL REFERENCES Cars (VIN), 
driver_licence_number INTEGER NOT NULL 
    REFERENCES Drivers (driver_licence_number) 
); 

INSERT INTO CarDrivers_staging 
    VALUES (1, 55), -- remains 
      (1, 99); -- insert 
        -- DELETE (1, 22) 

MERGE INTO CarDrivers 
    USING CarDrivers_staging S 
     ON S.VIN = CarDrivers.VIN 
     AND S.driver_licence_number = CarDrivers.driver_licence_number 
WHEN NOT MATCHED THEN 
    INSERT (VIN, driver_licence_number) 
     VALUES (VIN, driver_licence_number) 
WHEN NOT MATCHED BY SOURCE THEN 
    DELETE; 
+0

謝謝。我將不得不在今天晚些時候花點時間看看我能否理解它。 –

2

我懷疑這是否更有效率,但可能是「更清晰」,尤其是如果您沒有大量數據。當用戶提交更新汽車司機關係的表單時,爲什麼不先刪除CarDrivers中與其相關的所有關係,然後插入他們檢查的關係?或者,您可以在CarDrivers的兩列上都有uniq約束,然後只需擔心插入和刪除操作,而不是檢查代碼中的現有記錄。

+0

我想過刪除它們所有的第一,但似乎太沒效率了我。如果通過唯一的約束,你的意思是CarDrivers中的每一列都是唯一的,這將防止多個駕駛員與同一輛車相關聯,或者多個駕駛員與同一駕駛員相關聯。但是,如果您的意思是兩欄組合都是獨一無二的,那就是我擁有的方式。但是我仍然需要檢查現有的記錄,否則我的應用程序會收到數據庫錯誤。 –

+0

錯誤是否強制回滾?否則,你難道不能抓住那個特定的錯誤並繼續前進嗎? – imm

+1

我想我只會得到一個可能意味着任何數據庫錯誤的通用數據庫異常。一般來說,我喜歡編寫不會引發異常的代碼。 –