通过重用 postgres 索引或 bigserial 将数据从 staging table 插入到 2 tables

insert data from staging table to 2 tables by reusing postgres index or bigserial

我有 3 张桌子:

CREATE TABLE stage
(
  a1 text,
  b2 text,
  c3 text,
  d4 text,
  e5 text
);

CREATE TABLE main
(
  id bigserial PRIMARY KEY,
  a1 text,
  b2 text,
  c3 text
);

CREATE TABLE secondary (
  id bigserial PRIMARY KEY,
  mainid bigint,
  d4 text,
  e5 text,
  CONSTRAINT secondary_fkey FOREIGN KEY(mainid) REFERENCES main(id)
);

我想立即将 stage 中的数据插入 mainsecondary,但我不太确定如何通过在 [=14= 中重用生成的 bigserial 来做到这一点].我正在尝试 with query,但我在 secondary 中获得的行(指数)比预期的多。

dbfiddle

WITH tmp AS (
  INSERT INTO
    main (a1, b2, c3)
  SELECT
    a1,
    b2,
    c3
  FROM
    stage RETURNING id
)
INSERT INTO
  secondary (mainid, d4, e5)
SELECT
  tmp.id,
  stage.d4,
  stage.e5
FROM
  tmp,
  stage;

您的问题是您在最终 INSERT 语句中创建的与 FROM tmp, stage; 的交叉连接。如果您在阶段中有 10 行 table,这将生成 100 行而不是您想要的 10 行。

如果 (a1, b2, c3) 唯一标识 stage 中的一行,您可以将它们用于适当的连接条件:

WITH tmp AS (
  INSERT INTO main (a1, b2, c3)
  SELECT a1, b2, c3
  FROM stage 
  RETURNING *
)
INSERT INTO secondary (mainid, d4, e5)
SELECT tmp.id,
       stage.d4,
       stage.e5
FROM tmp 
  JOIN stage 
    on tmp.a1 = stage.a1 
   and tmp.b2 = stage.b2 
   and tmp.c3 = stage.c3;

如果那不可行(因为存在重复项),您可以为 main table 插入之前使用 nextval()

with stage_with_mainid as (
  select nextval(pg_get_serial_sequence('main', 'id')) as mainid,
         a1, b2, c3, d4, e5
  from stage       
), insert_main as (
  insert into main (id, a1, b2, c3) --<< this provides the generated new ID explictely
  select mainid, a1, b2, c3
  from stage_with_mainid
)
insert into secondary (mainid, d4, e5)
select mainid, d4, e5
from stage_with_mainid;