1

У меня есть следующая таблица:Обновление с помощью row_number() не работает, почему?

CREATE TABLE t_overview 
(
    obj_uid uuid, 
    obj_parent_uid uuid, 
    obj_no integer, 
    obj_text text, 
    obj_path text, 
    isdir integer, 
    intid bigint, 
    intparentid bigint 
) 

Я хочу, чтобы перейти от uuid к bigint и создали новые столбцы intid и intparentid. Мне нужно уникальное целое число (obj_uid является основным ключом) для intid, поэтому я просто хотел обновить row_number() over (order by ...).

Не работает. Поэтому я попытался записать результаты в таблицу temp и обновить через join. Но я получил 1 за каждые intid.

Но когда я выбираю из соединения, где я делаю обновление, я получаю 1, 2, 3, 4, 5, 6 и т. Д. Что мне не хватает?

DROP TABLE IF EXISTS mytable; 
CREATE TEMP TABLE mytable AS 
WITH CTE AS 
(
    SELECT obj_uid, obj_parent_uid, obj_no 
     , obj_text, obj_path, isdir 
     , intid as cteIntId 
     , intparentid as cteParentId 
     , row_number() over (order by obj_uid) as rn 
    FROM T_Overview 
) 
SELECT * FROM CTE; 

UPDATE T_Overview SET intid = mytable.rn 
FROM T_Overview AS bt 
INNER JOIN mytable 
    ON mytable.obj_uid = bt.obj_uid 


-- UPDATE T_Overview SET intid = CTE.rn FROM CTE; 
-- UPDATE T_Overview SET intparentid = CTE.intid FROM CTE; 
+0

'obj_parent_uid' является самоналожением (ссылка на' t_overview'), правильно? –

+0

@ Erwin Brandstetter: Правильно –

ответ

2

@Frank уже предоставил объяснения вашей ошибки.

Но вам не нужна временная таблица на все:

BEGIN; 
LOCK T_Overview; -- if there is concurrent write access 

WITH cte AS (
    SELECT obj_uid, obj_parent_uid 
     , row_number() OVER (ORDER BY obj_uid) AS intid 
    FROM T_Overview 
    ) 
UPDATE T_Overview t 
SET  intid  = upd.intid 
     , intparentid = upd.intparentid 
FROM (
    SELECT t1.*, t2.intid AS intparentid 
    FROM cte t1 
    LEFT JOIN cte t2 ON t2.obj_uid = t1.obj_parent_uid 
    ) upd 
WHERE t.obj_uid = upd.obj_uid; 

COMMIT; 

Сделки обертка и явную блокировка только необходимо, если может быть одновременным доступ к записи. (Тем более, что с темп стола, где у вас есть много больше временной интервал между ними.)

Предполагая, что ссылочную целостность - ограничение FK от T_Overview.obj_parent_uid к T_Overview.obj_uid. Значения NULL в obj_parent_uid переводятся в NULL в intparentid.

2

Ваше обновление неверно, нет никакой связи между T_Overview и (T_Overview + mytable).

Это один должен работать:

UPDATE T_Overview SET intid = mytable.rn 
FROM mytable 
WHERE mytable.obj_uid = T_Overview.obj_uid; 

Offtopic: Ваш CTE не имеет особого смысла, простой ВЫБРАТЬ даст вам те же результаты.

+0

Хм, очень интересно. Да, это правда. Я начал делать ненужный CTE, когда у меня возникли проблемы. Кажется, что PG делает неявное кросс-соединение, а таблица обновлений и таблица из двух разных объектов. Это объясняет, почему у меня возникли проблемы с синтаксисом, пока я не вышлю из таблицы. Очень странно ... Это стандартный SQL-код, или это странность PostGre? –

Смежные вопросы