Как переключить два идентификатора [PK] в базе данных postgres?

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

Как я могу сделать это в одном запросе SQL или транзакции?

Пример:

<code>UPDATE mytable SET id=2 WHERE ID=1;
UPDATE mytable SET id=1 WHERE ID=2
</code>
 SingleNegationElimination05 апр. 2012 г., 18:24
вместо изменения идентификаторов, можете ли вы использовать решение, в котором все остальные атрибуты изменены вместо этого?
 Tony Hopkinson05 апр. 2012 г., 15:54
Вы говорите, что записи, связанные с id = 1 после изменения, должны оставаться связанными с id = 1? т.е. вы не хотите менять зависимые таблицы?
 bartolo-otrit29 июн. 2015 г., 16:06
А как насчет замены содержимого вместо замены идентификаторов?
 Erwin Brandstetter17 сент. 2012 г., 12:48
Тесно связаны сthis question.
 paxdiablo05 апр. 2012 г., 15:43
Когда у вас есть целостность транзакции, вы не делаетеneed сделать это в одну строку !!

Ответы на вопрос(3)

Вы пробовали что-то вроде:

BEGIN;

CREATE TEMP TABLE updates ON COMMIT DROP AS
SELECT column1::int oldid, column2::int newid
FROM ( VALUES (1, 2), (2, 1) ) foo;

UPDATE mytable
FROM updates
SET id = newid
WHERE id = oldid;

--COMMIT;
ROLLBACK;

Конечно, откат комментируется и фиксируется, когда вы готовы к работе.

 sorin05 апр. 2012 г., 18:01
Вы определенно что-то пропустили наUPDATE.

Вы упоминаете внешние ключи, но остается неясным,id является ссылочным или ссылочным столбцом ограничения внешнего ключа.

Еслиid is the referenced column вы просто определяете ограничение ФКON UPDATE CASCADE, Тогда вы можете изменить свойid столько, сколько вы хотите. Изменения каскадируются в зависимости от столбцов.

Еслиid is the referencing column (никакие другие ограничения внешнего ключа не указывают на это), тогда есть другой, более быстрый путь, так какPostgreSQL 9.0, Вы можете использовать отложенный первичный или уникальный ключ. Рассмотрим следующую демонстрацию:

Note что вы не можете использовать это, если вы хотите сослатьсяid сforeign key ограничение из другой таблицы. Я цитирую руководствоВот:

The referenced columns must be the columns of a non-deferrable unique or primary key constraint in the referenced table.

Testbed:

CREATE TEMP TABLE t
( id integer
 ,txt text
 ,CONSTRAINT t_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY DEFERRED
);
INSERT INTO t VALUES
 (1, 'one')
,(2, 'two');

Обновить:

UPDATE t
SET    id = t_old.id
FROM   t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));

Результат:

SELECT * FROM t; 

id | txt
---+-----
2  | one
1  | two

Вы также можете объявить ограничениеDEFERRABLE INITIALLY IMMEDIATE и использоватьSET CONSTRAINTS ... DEFERRED в той же транзакции.

Обязательно прочтите подробности в руководстве:

CREATE TABLE SET CONSTRAINTS

Даже, кажется, работать сDEFERRABLE INITIALLY IMMEDIATE и нетSET CONSTRAINTS, Я отправилвопрос об этом.

 05 апр. 2012 г., 18:31
Я понимаю, что указанный столбец не может быть столбцом отложенного первичного ключа. Или я не прав?
 05 апр. 2012 г., 18:34
Как я прокомментировал ранее в ответе, который был удален, этого не произойдет, потому что в последней версии PG9.1 у вас не может быть FOREIGN KEY, указывающего на уникальный столбец с ограничением DEFERRABLE, а в вопросе конкретно упоминается о существовании. ФК.
 05 апр. 2012 г., 18:47
@ Эрвин: Я тоже удивился, когда читал вопрос, но, поскольку в заголовке написано «... ID [PK] ...», я предположил, что mytable.ID - это первичный ключ, и на него указывает некоторая не упомянутая таблица. Может быть, автор должен уточнить это.
 05 апр. 2012 г., 18:42
@ DanielV & # xE9; rit & # xE9 ;: Из вопроса о том,id является ссылочным или ссылочным столбцом ограничения внешнего ключа. Если это столбец ссылок, это будет работать.
 05 апр. 2012 г., 18:39
@Clodoaldo: Да, это важное ограничение для внешних ключей. Я добавил примечание к своему ответу ..
begin;
alter table mytable drop constraint_name;
UPDATE mytable SET id=-1 WHERE ID=1;
UPDATE mytable SET id=1 WHERE ID=2;
UPDATE mytable SET id=2 WHERE ID=-1;
alter table mytable add table_constraint;
commit;

Ваш ответ на вопрос