在PostgreSQL 9.5数据库中,我有不同类型的对象(每个对象都存储在自己的表中),这些对象在DAG中是相互关联的。为了表示此DAG,我设置了node
和edge
个表。 node
表只存储一个全局唯一的id,它将由存储对象的所有表共享:
CREATE TABLE node (
id SERIAL PRIMARY KEY NOT NULL
);
假设我的一个对象类型在表library
中。忽略其他字段,这个表只是:
CREATE TABLE library (
uuid INTEGER NOT NULL REFERENCES node(id),
id TEXT PRIMARY KEY NOT NULL
)
我可以将一个标识为XXX
的条目加载到library
中,如下所示:
WITH x AS (
INSERT INTO node (id) VALUES (DEFAULT) RETURNING id
)
INSERT INTO library (id, uuid) VALUES ('XXX', (SELECT id FROM x));
但是,我有一个引用外部资源的视图import.library
,我想从该视图加载public.library
en masse 。换句话说,我想做这样的事情:
INSERT INTO library (uuid, id)
WITH x AS (
INSERT INTO node (id) VALUES (DEFAULT) RETURNING id
)
SELECT (SELECT id FROM x), id FROM import.library;
这是不可能的,因为数据修改WITH
语句必须位于顶层。
我可以通过在DO
语句中使用匿名函数来实现相同的结果:
DO $$DECLARE l_id TEXT;
BEGIN
FOR x IN SELECT id FROM import.library
LOOP
WITH x AS (
INSERT INTO node (id) VALUES (DEFAULT) RETURNING id
)
INSERT INTO library (id, uuid) VALUES (l_id, (SELECT id FROM x));
END LOOP;
END$$;
这样可行,但我仍然想知道是否可以在简单的SQL语句中执行相同的操作而无需使用匿名函数。
答案 0 :(得分:2)
由于node
表中的uuid是由序列生成的,我能想到的唯一方法是翻转插入顺序:
WITH x AS (
INSERT INTO library (uuid, id)
SELECT nextval('node_id_seq'), id
FROM import_library
returning uuid
)
INSERT INTO node (id)
select uuid
from x