更新 row_number() 不起作用,为什么?
Update with row_number() not working, why?
我有以下 table:
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
。我需要 intid
的唯一整数(obj_uid
是主键),所以我只想用 row_number() over (order by ...)
.
更新
似乎没有用。所以我尝试将结果写入临时 table,并通过连接更新。但是我得到了 1
每 intid
.
但是当我 select 从连接进行更新时,我得到 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;
你的更新有误,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 会给你同样的结果。
已经为您的错误提供了解释。
但你根本不需要临时 table:
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;
只有在可以并发写入访问时才需要事务包装器和显式锁。 (对于临时 table 更是如此,中间有一个 多 更大的时间段。)
假设参照完整性 - 从 T_Overview.obj_parent_uid
到 T_Overview.obj_uid
的 FK 约束。 obj_parent_uid
中的 NULL 值在 intparentid
.
中转换为 NULL
我有以下 table:
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
。我需要 intid
的唯一整数(obj_uid
是主键),所以我只想用 row_number() over (order by ...)
.
似乎没有用。所以我尝试将结果写入临时 table,并通过连接更新。但是我得到了 1
每 intid
.
但是当我 select 从连接进行更新时,我得到 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;
你的更新有误,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 会给你同样的结果。
但你根本不需要临时 table:
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;
只有在可以并发写入访问时才需要事务包装器和显式锁。 (对于临时 table 更是如此,中间有一个 多 更大的时间段。)
假设参照完整性 - 从 T_Overview.obj_parent_uid
到 T_Overview.obj_uid
的 FK 约束。 obj_parent_uid
中的 NULL 值在 intparentid
.