使用WITH子句插入表无法在Postgres中工作

时间:2019-05-14 12:59:08

标签: sql postgresql

对不起,后续问题(来自INSERT into table if doesn't exists and return id in both cases

但是我找不到任何解决方案。

我有一个反馈表,其列是其他表的外键。对于前。 scopeid是作用域表中id列的前导键,类似地,userid是用户表中id列的外键,依此类推。

因此,我正在尝试在表中插入以下数据: 范围:首页, 用户名:abc 状态:固定 应用:demoapp

因此,要插入上述数据,我试图编写子查询以获取每个值的ID并使用该ID。另外,如果该值不存在,则插入并使用新ID将其插入反馈表中。

所以基本上,我试图插入多个表(如果不存在)并使用这些ID插入到最终表(即反馈表)中。

希望现在情况更加清楚

这是我的反馈表:

id  scopeid   comment   rating   userid   statusid   appid
3     1        test      5        2          1           2

所有id列都是其他表的外键,因此在下面的查询中,我尝试按名称获取id,如果不存在,则添加它们。

这是我的最后一个查询:

INSERT INTO feedbacks (scopeid, comment, rating, userid, statusid, appid)
VALUES
(
-- GET SCOPE ID
 (
  WITH rows_exists AS (
  SELECT id FROM scope 
  WHERE appid=2 AND NAME = 'application'),
  row_new AS (INSERT INTO scope (appid, NAME) SELECT 2, 'application' WHERE NOT EXISTS (SELECT id FROM scope WHERE appid=2 AND name='application') returning id)
  SELECT id FROM rows_exists UNION ALL SELECT id FROM row_new
 ),
-- Comment
 'GOD IS HERE TO COMMENT',
-- rating
 5,
-- userid
 (
  WITH rows_exists AS (
  SELECT id FROM users
  WHERE username='abc'),
  row_new AS (INSERT INTO users (username) SELECT 'abc' WHERE NOT EXISTS (SELECT id FROM users WHERE username='abc') returning id)
  SELECT id FROM rows_exists UNION ALL SELECT id FROM row_new
 ),
-- statusid
 (SELECT id FROM status WHERE NAME='received'),
-- appid
 (
  WITH rows_exists AS (
  SELECT id FROM apps
  WHERE name='google'),
  row_new AS (INSERT INTO apps (name) SELECT 'google' WHERE NOT EXISTS (SELECT id FROM apps WHERE NAME='google') returning id)
  SELECT id FROM rows_exists UNION ALL SELECT id FROM row_new
 )
)

但我收到以下错误消息:

with包含数据修改语句的子句必须位于顶层

通过这种方式或其他方法,我什至有可能实现这一目标。

1 个答案:

答案 0 :(得分:1)

以下代码插入不存在的ID,然后插入结果ID:

with s as (
      select id
      from scope
      where appid = 2 AND NAME = 'application'
     ),
     si as (
      insert into scope (appid, name)
          select v.appid, v.name
          from (values (2, 'application')) v(appid, name)
          where not exists (select 1 from scope s where s.appid = v.appid and s.name = v.name)
          returning id
     ),
     . . . similar logic for other tables
insert into feedback (scopeid, comment, . . . )
    select (select id from s union all select id from is) as scopeid,
           'test' as comment,
           . . .;

您应该确保在每个表中对于要查找的值都有唯一的约束。否则,您可能会遇到竞争状况,并最终在多线程环境中多次插入同一行。