我有下表:
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 ...)
进行更新。
似乎没有用。所以我试着将结果写入临时表,并通过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 :(得分: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没有多大意义,普通的SELECT会给你相同的结果。
答案 1 :(得分: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;
只有在可以进行并发写访问时才需要事务包装器和显式锁。 (对于临时表来说更是如此,你的中间有一个多更大的时间段。)
假设参照完整性 - 从T_Overview.obj_parent_uid
到T_Overview.obj_uid
的FK约束。 obj_parent_uid
中的NULL值在intparentid
中被转换为NULL。