PostgreSQL。更新联结点 table
PostgreSQL. Update junction table
我想更新我的交汇点 table 的行。不是字面上的更新,只插入新的元组并删除未插入的元组。
这是我的 tables:
用户table
-----------------------
|user_id |FullName |
-----------------------
|1 | John |
|2 | Michael |
|3 | Bryce |
地址table
-----------------------------------------
|address_id| country | city |
-----------------------------------------
| 1 | USA | New-York |
| 2 | Russia | Moscow |
| 3 | Germany | Berlin |
| 4 | UK | London |
这是连接 table 的路口
现在两个。
"user_address"
------------------------
| 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 万行,而用户只想删除一行怎么办。
在这种情况下,我将删除所有 100 万,并仅为一行插入 999.999.999。
那么,我怎样才能只插入新行并删除没有为我插入的行呢?
P.S。我正在使用 PostgreSQL。
更新
希望这个截图能解释我的问题。
这是我的路口 table:
我正在尝试更新用户的地址 - 在 junction:
中更改 user_id
UPDATE user_address SET user_id = 100 WHERE address_id = 25 RETURNING user_id
但是如果我使用这个查询,当我只想有一行 user_id = 100
时,它会将 user_id 都更改为 100
所以,问题是如何避免联结 table 更新中的重复。
首先要避免和防止“连接点 table”中的重复项,您需要通过添加约束使行唯一:
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)
这将确保您在指定的 table 中没有重复项。为了删除单行,您将必须指定两个列值。如果要删除具有特定 user_id
的所有行,则指定 user_id
;如果要删除带有 address_id
的所有行,请指定 address_id
.
您可以对您找到的 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 循环,因为您在这里处理完整的集合。
除此之外,附加的主键几乎没有用。
我想更新我的交汇点 table 的行。不是字面上的更新,只插入新的元组并删除未插入的元组。
这是我的 tables:
用户table
-----------------------
|user_id |FullName |
-----------------------
|1 | John |
|2 | Michael |
|3 | Bryce |
地址table
-----------------------------------------
|address_id| country | city |
-----------------------------------------
| 1 | USA | New-York |
| 2 | Russia | Moscow |
| 3 | Germany | Berlin |
| 4 | UK | London |
这是连接 table 的路口 现在两个。
"user_address"
------------------------
| 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 万行,而用户只想删除一行怎么办。
在这种情况下,我将删除所有 100 万,并仅为一行插入 999.999.999。
那么,我怎样才能只插入新行并删除没有为我插入的行呢?
P.S。我正在使用 PostgreSQL。
更新
希望这个截图能解释我的问题。
这是我的路口 table:
我正在尝试更新用户的地址 - 在 junction:
UPDATE user_address SET user_id = 100 WHERE address_id = 25 RETURNING user_id
但是如果我使用这个查询,当我只想有一行 user_id = 100
时,它会将 user_id 都更改为 100
所以,问题是如何避免联结 table 更新中的重复。
首先要避免和防止“连接点 table”中的重复项,您需要通过添加约束使行唯一:
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)
这将确保您在指定的 table 中没有重复项。为了删除单行,您将必须指定两个列值。如果要删除具有特定 user_id
的所有行,则指定 user_id
;如果要删除带有 address_id
的所有行,请指定 address_id
.
您可以对您找到的 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 循环,因为您在这里处理完整的集合。
除此之外,附加的主键几乎没有用。