PostgreSQL。更新联结表

时间:2019-05-25 05:32:36

标签: sql postgresql junction-table

我想更新我的联结表的行。并非从字面上进行更新,仅插入新的元组并删除未插入的元组。

这是我的桌子:

用户表

-----------------------
|user_id   |FullName |
-----------------------
|1      | John    |
|2      | Michael |
|3      | Bryce   |

地址表

-----------------------------------------
|address_id|    country    |    city     |
-----------------------------------------
|    1     |      USA      |    New-York |
|    2     |     Russia    |    Moscow   |
|    3     |    Germany    |    Berlin   |
|    4     |      UK       |    London   |

这是连接表的结点表     现在两个。

“用户地址”

------------------------
| user_id | address_id |
------------------------
|   1     |      1     |
|   1     |      2     |
|   2     |      3     |
|   3     |      1     |

例如,我想在交界处插入一个新值并使它像这样:

------------------------
| user_id | address_id |
------------------------
|   1     |      1     |
|   1     |      3     |
|   2     |      4     |

是的,我可以这样做:

DELETE FROM user_address WHERE address_id = 1;
INSERT INTO user_address VALUES (1, 3);

但是,如果我要有一百万行,而用户只想删除一行,该怎么办?
在这种情况下,我将删除全部100万,只在一行中插入999.999.999。

那么,我如何只插入新行并删除那些没有为我插入的行?

P.S。我正在使用PostgreSQL。

UPDATE
希望此屏幕截图可以解释我的问题。 这是我的联结表: enter image description here
我正在尝试更新用户的地址-在联结中更改user_id:

UPDATE user_address SET user_id = 100 WHERE address_id = 25 RETURNING user_id

但是,如果我只使用user_id = 100的一行,它将使用user_id更改为100。
enter image description here
因此,问题是如何避免在联结表更新中出现重复项。

2 个答案:

答案 0 :(得分:1)

您可以执行与找到的MySQL解决方案相同的操作,只是语法不同。

对于INSERT,您应该添加一个UNIQUE INDEX

CREATE UNIQUE INDEX idx_address_users ON user_address (address_id, user_id);

...然后可以使用ON CONFLICT子句(在PostgreSQL 9.5中引入)来使重复的行被忽略,例如:

INSERT INTO user_address (user_id, address_id)
VALUES (100, 25), (101, 25), (102, 25)
ON CONFLICT (idx_address_users) DO NOTHING -- ignore duplicate new rows
RETURNING user_id;

DELETE FROM user_address WHERE address_id = 25 AND user_id NOT IN (100, 101, 102);

...或从用户端:

INSERT INTO user_address (user_id, address_id)
VALUES (100, 25), (100, 26), (100, 27)
ON CONFLICT (idx_address_users) DO NOTHING -- ignore duplicate new rows
RETURNING address_id;

DELETE FROM user_address WHERE user_id = 100 AND address_id NOT IN (25, 26, 27);

但是,这两种方法都要求您的应用程序在这里处理完整的集合时执行完整的load-modify-save周期。

除此之外,额外的主键几乎没有用。

答案 1 :(得分:0)

首先要避免并防止“ 连接表”中出现重复,您需要通过添加约束使行唯一:

ALTER TABLE user_address ADD CONSTRAINT uq_user_addr UNIQUE(user_id, address_id)

-- OR if there is no primary key in your user_address table

ALTER TABLE user_address ADD PRIMARY KEY (user_id, address_id)

这将确保您在指定表中没有重复项。为了删除单个行,您将必须同时指定两个列值。如果要删除具有特定user_id的所有行,则可以指定user_id;如果要使用address_id删除所有行,请指定address_id