更好的方式来插入多个表,从SQL WITH语句多个重新调整的值

Lab*_*oDJ 6 sql postgresql

好吧,标题可能看起来有点奇怪,但这是我的情况.我正在使用PostgreSQL,最新版本.

我有一个名为的架构

schema_ex
Run Code Online (Sandbox Code Playgroud)

我有3个表叫

A B C
Run Code Online (Sandbox Code Playgroud)

表A具有在插入时自动分配的唯一ID(串行)

id
Run Code Online (Sandbox Code Playgroud)

我想插入40条记录

前22

  • 表A上有22条记录,包含3列3个值:NULL,'1',1..22
  • 表B中的22,包含来自前一个插入的表A返回的2列的2个值:id,1..22
  • 我在表A中插入的每条记录在表C中有5条记录,包含从第一个插入的表A返回的2列的2个值:id,1..22

下一个18

  • 表A上有18条记录,包含3列3个值:NULL,'2',23..40
  • 表B中的18,包含来自前一个插入的表A返回的2列的2个值:id,23..40
  • 我在表A中插入的每条记录在表C中有5条记录,包含从第一个插入的表A返回的2列的2个值:id,23..40

41..N ......

  • (为方便起见)

到目前为止我的代码是这样的

SET schema 'schema_ex';
DO
$do$
BEGIN 
FOR j IN 1..22 LOOP
  WITH i1 AS (
    INSERT INTO A (col_a, col_b, col_c) VALUES (NULL, '2', j) RETURNING id, col_c
  )
,  i2 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i3 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i4 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i5 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i6 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
INSERT INTO B (id, col_c)
SELECT id, col_c FROM i1;
END LOOP;
END
$do$;

DO
$do$
BEGIN 
FOR j IN 23..40 LOOP
  WITH i1 AS (
    INSERT INTO A (col_a, col_b, col_c) VALUES (NULL, '2', j) RETURNING id, col_c
  )
,  i2 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i3 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i4 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i5 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
,  i6 AS (
    INSERT INTO C (id, col_c)
    SELECT id, col_c FROM i1
    )
INSERT INTO B (id, col_c)
SELECT id, col_c FROM i1;
END LOOP;
END
$do$;
Run Code Online (Sandbox Code Playgroud)

它有效,但不是那么优雅,所以我做了一个功能

CREATE OR REPLACE FUNCTION test.tmp()
RETURNS text AS
$BODY$
DECLARE
    rec tmp_table%ROWTYPE;
BEGIN
    FOR i IN 1..22 LOOP
        WITH last AS (
        INSERT INTO schema_ex.A (col_a, col_b, col_c)
        VALUES (NULL, '1', i) RETURNING id, col_c
    )
    INSERT INTO tmp_table
    SELECT id, col_c FROM last;
    END LOOP;

    FOR i IN 23..40 LOOP
        WITH last AS (
        INSERT INTO schema_ex.A (col_a, col_b, col_c)
        VALUES (NULL, '2', i) RETURNING id, col_c
    )
    INSERT INTO tmp_table
    SELECT id, col_c FROM last;
    END LOOP;

    FOR rec IN EXECUTE('SELECT * FROM tmp_table') LOOP
    INSERT INTO schema_ex.B (id, col_c)
    VALUES (rec.id, rec.col_c);

    FOR j IN 1..5 LOOP
        INSERT INTO schema_ex.C (text_id, col_c)
        VALUES (rec.id, rec.col_c);
    END LOOP;
    END LOOP;

    RETURN 'ok';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
Run Code Online (Sandbox Code Playgroud)

但即使它有效,我发现它有点奇怪,是否有任何简单/优雅的方式来满足我的需求?

dev*_*and 1

据我所知有一个特殊的功能吗

with last as (
  insert into schema_ex.A select null, '1', i from generate_series( 1, 22 ) as i returning id, col_c;
)
Run Code Online (Sandbox Code Playgroud)

仅作为示例。

这对你有用吗?