PostgreSQL. Обновить таблицу соединений - PullRequest
0 голосов
/ 25 мая 2019

Я хочу обновить строку моей соединительной таблицы.Не буквально обновлять, вставлять только новые кортежи и отбрасывать те, которые не были вставлены.

Вот мои таблицы:

таблица пользователей

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

Это таблица Junction для соединения двух.

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

Но что, если у меня будет 1 миллион строк, и пользователь захочет удалить только однустрока.
В этом случае я удалю все 1 миллион и вставлю 999.999.999 только для ОДНОЙ строки.

Итак, как я могу вставить только новые строки и отбросить те, которые не были вставлены для меня?

PS Я использую PostgreSQL.

ОБНОВЛЕНИЕ
Надеюсь, что эти скриншоты объяснят мою проблему.Вот моя таблица соединений: 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 ]

1 голос
/ 25 мая 2019

Вы можете сделать то же самое, что и для решения 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);

Однако оба эти подхода требуют, чтобы ваше приложение выполняло полный цикл загрузки-изменения-сохранения, поскольку вы имеете дело с полными коллекциями здесь.

Кроме того, дополнительный первичный ключ в значительной степени бесполезен.

0 голосов
/ 25 мая 2019

Во-первых, чтобы избежать и предотвратить дубликаты в вашей " соединительной таблице ", вам нужно сделать строки уникальными, добавив ограничение:

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.

...