在发生冲突时,NOTHHING不会阻止查询继续执行下一条插入语句

时间:2019-05-22 19:39:22

标签: postgresql

我正在使用WITH运行两个INSERT语句(表A和表B)。第一个INSERT语句具有ON CONFLICT子句,如果A.name中有重复项,则不要。第二条语句依赖于成功插入到表A中,因此它试图在表B中输入空值。NOTHHING对第一条语句不执行任何操作,但是第二条语句继续执行,如何停止它?

WITH first_insert AS (INSERT INTO 
                groups(group_cuid,group_name,created_by,date_created)
                VALUES ($1,$2,(SELECT user_id 
                               FROM users 
                               WHERE users.cognito_id='${created_by}'), 
                (SELECT now()::timestamp))
                ON CONFLICT ON CONSTRAINT group_name_unique DO NOTHING
                RETURNING id,created_by
                )
INSERT INTO groups_users_rel(group_id,user_id,is_admin,date_joined)
VALUES (
        (SELECT id FROM first_insert),
        (SELECT created_by FROM first_insert),
        true, 
        (SELECT now()::timestamp)
       )
RETURNING *

如果在GROUPS表中发生插入,我希望在GROUPS_USERS_REL表中进行插入。如果有冲突,我希望整个查询结束。而是在第一次插入时根据CONFLICT将空值插入GROUPS_USERS_REL。

如果有更简便的方法来进行上述任何操作,请随时发表评论。

2 个答案:

答案 0 :(得分:1)

INSERT INTO ... VALUES (...)将始终尝试使用您提供的值列表准确插入一条记录。当查询SELECT id FROM first_insert不返回记录时,子查询(SELECT id FROM first_insert)的计算结果为NULL,因此这就是表中的内容。

如果要插入可变数量的行(即零或一),则需要一个INSERT INTO ... SELECT ...语句,其中SELECT决定要添加的行(如果有)。

在您的情况下,它看起来像这样:

WITH first_insert AS (
  ...
)
INSERT INTO groups_users_rel(group_id,user_id,is_admin,date_joined)
SELECT
  id,
  created_by,
  true, 
  now()::timestamp
FROM first_insert
RETURNING *

答案 1 :(得分:0)

Nick Barnes给出的答案解决了您遇到的问题。但是,我注意到了另一个清理您的代码的机会:

代替使用VALUES子句SELECT user_id FROM users,而是提供要在查询参数中插入的常量。制作完整的查询文本:

WITH first_insert AS (
INSERT INTO groups (group_cuid, group_name, created_by, date_created)
  SELECT 
      $1
    , $2
    , user_id
    , now()
  FROM users
  WHERE users.cognito_id = '${created_by}'
  ON CONFLICT ON CONSTRAINT group_name_unique DO NOTHING
  RETURNING id, created_by, true, now()
)
INSERT INTO groups_users_rel (group_id, user_id, is_admin, date_joined)
SELECT *
FROM first_insert 
RETURNING *;