简体   繁体   English

PostgreSQL的。 更新联结表

[英]PostgreSQL. Update junction table

I want to update my junction table's row. 我想更新我的联结表的行。 Not literally update, insert only new tuples and drop the ones that were not inserted. 没有字面上的更新,仅插入新的元组,然后删除未插入的元组。

Here's my tables: 这是我的桌子:

users table 用户表

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

addresses table 地址表

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

This is the Junction table to connect the two now. 这是现在将两者连接的连接表。

"user_address" “user_address”

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

For example I want to insert a new values in my junction and make it like this: 例如,我想在交界处插入一个新值并使它像这样:

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

And, yeah, I can just do that: 而且,是的,我可以这样做:

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

But, what if I'll have 1 million of rows, and user want to delete just one row. 但是,如果我要有一百万行,而用户只想删除一行,该怎么办?
In this case I'll delete all 1 million and insert 999.999.999 only for ONE row. 在这种情况下,我将删除全部100万,仅对一行插入999.999.999。

So, how can I insert only new rows and drop the ones that were not inserted for me? 那么,如何才能只插入新行并删除那些没有为我插入的行呢?

PS I'm using PostgreSQL. PS我正在使用PostgreSQL。

UPDATE UPDATE
Hope this screenshots will explain my problem. 希望此屏幕截图可以解释我的问题。 Here's my junction table: 这是我的联结表: 在此处输入图片说明
I'm trying to update users for address - change user_id in junction: 我正在尝试更新用户的地址-在联结中更改user_id:

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

But if I use this query it will change both user_id to 100 when I want to have only one row with user_id = 100 但是,如果我只想使用user_id = 100的一行,它将使用user_id更改为100
在此处输入图片说明
So, question is How to avoid duplicates in junction's table update. 因此,问题是如何避免在联结表更新中重复。

You can do the same as for the MySQL solution you've found, just that the syntax is different. 您可以执行与找到的MySQL解决方案相同的操作,只是语法不同。

For the INSERT , you should add a UNIQUE INDEX : 对于INSERT ,您应该添加UNIQUE INDEX

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

...and then you can use the ON CONFLICT clause (introduced in PostgreSQL 9.5), to have the duplicate rows being ignored, eg: ...然后您可以使用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);

...or from the user side: ...或从用户方面:

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);

However, both of these approaches require your application to do a full load-modify-save cycle as you are dealing with complete collections here. 但是,这两种方法都要求您的应用程序在这里处理完整的集合时执行完整的负载-修改-保存周期。

Besides that, the additional primary key is pretty much useless. 除此之外,额外的主键几乎没有用。

First to avoid and prevent duplicates in your " junction table ", you need to make the rows unique by adding a constraint: 首先,为了避免和防止“ 联结表 ”中出现重复,您需要通过添加约束使行唯一:

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)

This will ensure that you have no duplicates in the specified table. 这将确保您在指定表中没有重复项。 In order to delete a single row, you will then have to specify both column values. 为了删除单个行,您将必须同时指定两个列值。 If you want to delete all rows with a specific user_id then you specify the user_id ; 如果要删除具有特定user_id所有行,则可以指定user_id ; If you want to delete all rows with address_id you specify the address_id . 如果要删除所有具有address_id行,请指定address_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM