跨越三个表的多个插入捕获postgres

时间:2015-12-01 00:13:24

标签: postgresql

我有三张表,我已将其缩写为以下

create table top (top_id serial, top_name text);
create table mid (mid_id serial, top_id integer, mid_name text);
create table bot (bot_id serial, mid_id integer, bot_name text);

我想要实现的是

  • 将值插入到顶部,然后捕获它的ID
  • 使用相同的top_id
  • 将多个值插入到mid中
  • 对于mid中的每个值,使用每个mid_id将多个值插入到bot中。

因此,最终结果可能看起来像

top
----
1, first_top
2, second_top

mid
---
1, 1, first_mid_for_first_top
2, 1, second_mid_for_first_top
3, 2, first_mid_for_second_top

bot
---
1, 1, first_bot_for_first_mid
2, 1, second_bot_for_first_mid
3, 3, first_bot_for_third_mid

我的第一种方法是尝试使用一堆嵌套的CTE,但我无法将其转换为有效的语法(考虑到这一点,我认为它不是正确的方法)。

我的第二种方法是尝试将值存储到某种变量中,但我不知道如何在pg命令行工具之外执行此操作。

我所追求的是类似于

的东西
top_id_one = insert into top(null, 'first_top') returning top_id
mid_id_one = insert into mid(null, top_id_one, 'first_mid_for_first_top) returning mid_id
insert into bot(null, mid_id_one, 'first_bot_for_first_mid')

纯粹的sql"例如,我可以粘贴到PG管理员。

我意识到上面的例子中存在一些问题(例如使用' top'作为表名)。我的探索已经避免了这些问题,但我试图找到能够使我的例子有意义的表名。

2 个答案:

答案 0 :(得分:2)

您可以通过对插入mid_id的行进行编号,选择使用哪个bot将值插入mid。 使用这些行号(rn)来标识插入bot的值:

with top_ins as (
    insert into top (top_name)
    values ('first_top')
    returning top_id
    ),
mid_ins as (
    insert into mid (top_id, mid_name)
    select top_id, name
    from (
        values 
            ('first_mid'), 
            ('second_mid')
        ) v(name)
    cross join top_ins
    returning mid_id
    ),
mid_ins_rn as (
    select mid_id, row_number() over() rn
    from mid_ins
    order by 1
    )
insert into bot (mid_id, bot_name)
select mid_id, name
from (
    values 
        (1, 'first_bot_for_first_mid'), 
        (1, 'second_bot_for_first_mid'),
        (2, 'first_bot_for_second_mid')
    ) v(rn, name)
join mid_ins_rn
using (rn);

结果:

select * from top;

 top_id | top_name  
--------+-----------
      1 | first_top
(1 row)

select * from mid;

 mid_id | top_id |  mid_name  
--------+--------+------------
      1 |      1 | first_mid
      2 |      1 | second_mid
(2 rows)

select * from bot;

 bot_id | mid_id |         bot_name         
--------+--------+--------------------------
      1 |      1 | first_bot_for_first_mid
      2 |      1 | second_bot_for_first_mid
      3 |      2 | first_bot_for_second_mid
(3 rows)

答案 1 :(得分:1)

如果您可以按顺序运行sql语句,则可以使用序列的当前值(弹出表中最后一个插入的id的currval)来获取top,mid,bot的值:

String s = (String) value;

这应该给出确切的结果,您在示例中显示了最终结果。