使用 CTE 插入多个表对我不起作用

Inserting into multiple tables with a CTE Not working for me

我在这里看到了一些关于将一些常见的 CTE 用例插入到多个表中的答案,当尝试执行相同的步骤时,我最终得到一个错误

Missing From-clause entry for table "first_insert" position 824.

我的CTE表达式如下,

with first_insert as (
    insert into listing (title, slug, price, min_quantity, serves, currency_name, currency_symbol, img_url, description,
                         location, g_map_address, vendor_id)
        values ('hello', 'hello-1234', 1, 12, 10, 'eur', '€','url.jpg',
                'description', point(24.5498, 16.26), 'gmap', 1)
        RETURNING id
),
     second_insert as (
         insert into category (name, suggested_name, link, rel_link, listing_id)
             select 'name', 'name', 'link', 'rel_link', id
             from first_insert
     ),
     third_insert as (
         insert into allergen (name, suggested_name, link, rel_link, listing_id)
             select 'name', 'name', 'link', 'rel_link', id
             from first_insert
     )
insert into image(listing_id, img_url) select first_insert.id, 'imgUrl';

1 - 我怎样才能让它工作,因为插入不需要 from 所以不知道从哪里开始

2 - 就性能而言,这是执行这些类型的插入的最佳方式吗?

3 - 这是否被归类为安全插入,如果任何一个插入失败并且已经执行的插入被回滚?

4 - 就性能和安全性而言,是否有更好的总体方式来执行此类插入?

1 - How can I get this working, as inserts don't require from so not sure where to even start with that

它抱怨 "final" 查询,其中没有 FROM 子句。应该是这样的:

...
insert into image(listing_id, img_url) select id, 'imgUrl' from first_insert;

2 - Is this the best way in terms of performance to execute these types of inserts?

性能应该类似于执行 BEGIN + 将 4 个插入作为单独的查询 + COMMIT。它可能稍微快一些,因为您正在保存应用程序和数据库之间的网络往返,但我认为这不会对普通应用程序产生影响。我会用你觉得更 readable/maintainable 的任何方式。

3 - Is this classified as a safe inserts such that if any one of the inserts fails with the already executed inserts be rolled back?

是的,Postgres 中的查询会在它们自己的事务中自动执行(如果您还没有启动自己的事务)。这意味着它的全部或 none 效果都会提交到磁盘,但永远不会部分。

4 - Is there a better overall way of doing such an insert in terms of performance and safety?

我认为没有更好的方法来提高性能。为了安全起见,这与 运行 4 在事务中分别插入一样安全。

对于 maintainability/readability,我认为在事务中分别执行 4 次插入会更好一些。它不那么深奥,更灵活。如果将来您只想在满足特定条件时才插入 allergen 怎么办?如果您单独执行查询,那么添加一个 if 非常容易,但如果您在一个大查询中执行所有查询,它就会变得更加复杂。