How to update or insert data with WITH subquery? and avoid `PG::UndefinedTable: ERROR: missing FROM-clause entry for table` error

How to update or insert data with WITH subquery? and avoid `PG::UndefinedTable: ERROR: missing FROM-clause entry for table` error

我正在尝试 运行 简单 sql 查询:

    <<-SQL.squish
      WITH payloads as (
        INSERT into text_payloads (text, created_at, updated_at)
          SELECT text, created_at, updated_at
          FROM text_messages
        RETURNING id, text, created_at, updated_at
      )
      UPDATE text_messages
      SET
        payload_id = text_payloads.id,
        payload_type = 'TextPayload'
      WHERE
        text_messages.text = text_payloads.text AND
        text_messages.created_at = text_payloads.created_at AND
        text_messages.updated_at = text_payloads.updated_at
    SQL

但出现此错误:

PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "text_payloads"
LINE 1: ...d_type = 'TextPayload' WHERE text_messages.text = text_paylo...
                                                         

我已经尝试添加 FROM payloads 甚至 LEFT OUTER JOIN text_payloads,但没有任何帮助。如何使用 WITH 子查询及其结果实现此更新或类似的插入操作?

非常感谢您!

错误信息很明确:在你的UPDATE语句中没有FROM子句来执行CTE之间的连接(我猜你想使用CTE而不是 text_payloads) 和 text_messages.
正确的语法是:

WITH payloads as (
  INSERT into text_payloads (text, created_at, updated_at)
    SELECT text, created_at, updated_at
    FROM text_messages
  RETURNING id, text, created_at, updated_at
)
UPDATE text_messages
SET
  payload_id = payloads.id,
  payload_type = 'TextPayload'
FROM payloads  
WHERE
  text_messages.text = payloads.text AND
  text_messages.created_at = payloads.created_at AND
  text_messages.updated_at = payloads.updated_at 

参见demo

这是工作代码

    <<-SQL.squish
      WITH payloads as (
        INSERT into text_payloads (text, created_at, updated_at)
          SELECT text, created_at, updated_at
          FROM text_messages
        RETURNING id, text, created_at, updated_at
      )
      UPDATE text_messages
      SET
        payload_id = text_payloads.id,
        payload_type = 'TextPayload'
      FROM payloads, text_payloads
      WHERE
        text_messages.text = text_payloads.text AND
        text_messages.created_at = text_payloads.created_at AND
        text_messages.updated_at = text_payloads.updated_at
    SQL