更新多个多对多关系

时间:2011-10-06 02:35:30

标签: sql sql-server entity-framework ado.net

我有两张桌子,汽车和司机,由第三张桌子CarDrivers加入,以多对多的关系。

我的用户界面允许用户检查与当前汽车相关的任意数量的驱动程序。每个检查表明应该在CarDrivers表中输入一行。

我的问题是:当用户提交表单时,更新这些行的最有效方法是什么?

我需要检查每个已检查项目的CarDrivers并为其中的每一项删除一行,同时保留未更改的项目。

我看到的唯一方法是一次一个地浏览每个组合,并添加尚未存在的组合或删除那些需要删除的组合。有一种更光滑的方式吗?

我可以使用Entity Frameworks 4,ADO.NET,直接SQL查询或存储过程。

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:2)

我怀疑这种效率更高,但“更光滑”,也许,特别是如果你没有大量的数据。当用户提交更新汽车 - 驾驶员关系的表单时,为什么不首先删除与他们相关的CarDrivers中的所有关系,然后只插入他们检查的那些?或者,您可以在CarDrivers中的两列上都有uniq约束,然后只需要担心插入和删除,而不是检查代码中的现有记录。