Postgres:INSERT包含WITH语句

时间:2016-04-17 17:13:36

标签: postgresql

在PostgreSQL 9.5数据库中,我有不同类型的对象(每个对象都存储在自己的表中),这些对象在DAG中是相互关联的。为了表示此DAG,我设置了nodeedge个表。 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语句中执行相同的操作而无需使用匿名函数。

1 个答案:

答案 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