我有两张桌子,汽车和司机,由第三张桌子CarDrivers加入,以多对多的关系。
我的用户界面允许用户检查与当前汽车相关的任意数量的驱动程序。每个检查表明应该在CarDrivers表中输入一行。
我的问题是:当用户提交表单时,更新这些行的最有效方法是什么?
我需要检查每个已检查项目的CarDrivers并为其中的每一项删除一行,同时保留未更改的项目。
我看到的唯一方法是一次一个地浏览每个组合,并添加尚未存在的组合或删除那些需要删除的组合。有一种更光滑的方式吗?
我可以使用Entity Frameworks 4,ADO.NET,直接SQL查询或存储过程。
答案 0 :(得分:4)
这正是MERGE
语法被发明来处理的情况,特别是WHEN NOT MATCHED BY SOURCE
子句。
一般来说,将当前状态值放入临时表,然后使用MERGE
在一次点击中处理INSERT
和DELETE
操作。
这是一个简短的草图:
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约束,然后只需要担心插入和删除,而不是检查代码中的现有记录。