更新多个多对多关系

发布于 2024-12-08 10:25:40 字数 354 浏览 0 评论 0原文

我有两个表“Cars”和“Drivers”,它们与第三个表“CarDrivers”以多对多关系连接。

我的 UI 允许用户检查与当前汽车关联的任意数量的驾驶员。每项检查都表明应将一行输入 CarDrivers 表中。

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

我需要遍历并为每个已检查的项目在 CarDrivers 中添加一行,并为每个未检查的项目删除一行,同时保留那些未更改的项目。

我看到的唯一方法是一次一个地检查每个组合,然后添加那些不存在的组合或删除那些需要删除的组合。有更圆滑的方法吗?

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

I have two tables, Cars and Drivers, that are joined by a third table, CarDrivers, in a many-to-many relationship.

My UI allows the user to check any number of drivers associated with the current car. Each check indicates that a row should be entered into the CarDrivers table.

My question is: what's the most efficient way to update those rows when the user submits the form?

I need to go through and add a row into CarDrivers for each item that was checked and delete one for each item that was unchecked, while leaving those that have not changed.

The only way I see is to go through each combination, one at a time, and add those that don't already exist or remove those that need to be removed. Is there a slicker way?

I can use Entity Frameworks 4, ADO.NET, straight SQL queries or stored procedures.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

守护在此方 2024-12-15 10:25:40

这正是 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;

This is exactly the scenario the MERGE syntax was invented to handle, notably the WHEN NOT MATCHED BY SOURCE clause.

Broadly speaking, put the current state values into a staging table then using MERGE to handle the INSERT and DELETE actions in one hit.

Here's a brief sketch:

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;
别低头,皇冠会掉 2024-12-15 10:25:40

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

I doubt this is more efficient, but "slicker", maybe, particularly if you don't have a huge amount of data. When a user submits a form that updates the cars-drivers relationships, why not first delete ALL relationships in CarDrivers related to them and then insert just the ones they checked? Alternatively, you could have a uniq constraint on both columns in CarDrivers, and then just worry about inserting and deleting, rather than checking for existing records in your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文