【问题标题】:Returning Index of inserted rows in a multiple row insert query in Postgres在 Postgres 中的多行插入查询中返回插入行的索引
【发布时间】:2019-12-09 21:49:33
【问题描述】:

我正在尝试在 PostgresSQL 11.2 中使用一个插入 SQL 查询插入多行(大约 1k)。像这样:

insert into foo(id) values(6),(5),(4),(3),(2) ON CONFLICT DO NOTHING RETURNING id;

它返回很好的插入行的 id。但如果获取插入行的索引(从 0 开始)对我来说会很棒。

例如,考虑在 id 为 5 和 3(索引 1 和 3)的行中插入 5 行冲突,目标是这样的:

indexes
------------
0
2
4

有什么想法吗?对我来说只用一个查询就很重要。

【问题讨论】:

    标签: sql postgresql upsert


    【解决方案1】:

    我认为您不能返回不在目标表中的值。但假设这些值是唯一的,您可以使用join 来计算:

    with v as (
          select v.*
          from (values(0, 6), (1, 5), (2, 4), (3, 3), (4, 2)
               ) v(idx, id)
         ),
         i as (
           insert into foo(id)
              select id
              from v
              on conflict do nothing
              returning id
         )
    select v.*
    from v join
         i
         on v.id = i.id;
    

    【讨论】:

    • 您的答案结合@Jim 解决方案(使用 row_number )效果很好。
    • @A.F.N 。 . .具有讽刺意味的是,我打算在解决方案中自动生成“idx”。但是,我认为假设值的特定顺序是不合理的——而且您似乎关心顺序。
    【解决方案2】:

    恐怕无法返回您要插入的表中不存在的值。

    也许CTE 和窗口函数row_number 的组合可以解决问题:

    测试数据

    CREATE TABLE foo(id INT PRIMARY KEY);
    INSERT INTO foo VALUES (5),(3);
    

    查询

    WITH k AS (
      WITH j AS (
        VALUES (6),(5),(4),(3),(2)  -- here you place your 1k entries!
      ) SELECT column1,row_number() OVER (ORDER BY 1)-1 AS idx FROM j
    ), l AS (
      INSERT INTO foo SELECT DISTINCT column1 FROM k
      ON CONFLICT DO NOTHING RETURNING id)
    SELECT idx FROM l
    JOIN k ON k.column1 = l.id ORDER BY idx;
    
     idx 
    -----
       0
       2
       4
    (3 Zeilen)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 1970-01-01
      • 2018-09-03
      • 2014-05-05
      • 2013-02-27
      • 2013-10-31
      相关资源
      最近更新 更多