【问题标题】:How to insert in multiple tables with a single API call in Supabase如何在 Supabase 中使用单个 API 调用插入多个表
【发布时间】:2021-12-04 07:37:52
【问题描述】:

这是我的表的简化结构 - 2 个主表,1 个关系表。
为此处理插入 API 的最佳方法是什么? 如果我只有一个客户和 Supabase:

- First API call to insert book and get ID
- Second API call to insert genre and get ID
- Third API call to insert book-genre relation

这是我能想到的,但是 3 个 API 调用似乎是错误的。
有没有一种方法可以通过我的客户端的一个 API 调用插入到这 3 个表中,像我可以调用的单个 postgres 函数吗?
请分享 API 的一般示例,谢谢!

【问题讨论】:

    标签: postgresql supabase supabase-database


    【解决方案1】:

    您是否有任何理由需要通过一次调用来执行此操作?我从您的结构中假设您不会为您创建的每本书创建一个新的genre,所以大多数时候,您只是插入一个book 记录和一个book_gen_rel 记录。在现实世界中,您可能会拥有属于多种类型的书籍,因此最终您将更改函数以在一次调用中处理插入一本书和多种类型。

    话虽如此,也有两种方法可以解决这个问题。您可以从客户端进行多个 API 调用(这样做确实没有问题——这很常见)。其次,如果您创建一个 PostgreSQL 函数并使用 .rpc() 调用它,则可以在一次调用中完成所有操作。

    仅使用客户端调用在每个表中插入记录的示例:

        const { data: genre_data, error: genre_error } = await supabase
          .from('genre')
          .insert([
            { name: 'Technology' }
          ]);
        const genre_id = genre_data[0].id;  
        const { data: book_data, error: book_error } = await supabase
          .from('book')
          .insert([
            { name: 'The Joys of PostgreSQL' }
          ]);
        const book_id = book_data[0].id;
        const { data: book_genre_rel_data, error: book_genre_rel_error } = await supabase
          .from('book_genre_rel_data')
          .insert([
            { book_id, genre_id }
          ]);
    

    这里有一条 SQL 语句可以一次插入到 3 个表中:

    WITH genre AS (
      insert into genre (name) values ('horror') returning id
    ),
    book AS (
      insert into book (name) values ('my scary book') returning id
    )
    insert into book_genre_rel (genre_id, book_id) 
      select genre.id, book.id from genre, book
    

    现在这是一个 PostgreSQL 函数,可以在一个函数调用中完成所有操作:

    CREATE OR REPLACE FUNCTION public.insert_book_and_genre(book_name text, genre_name text)
        RETURNS void language SQL AS
    $$
      WITH genre AS (
        insert into genre (name) values (genre_name) returning id
      ),
      book AS (
        insert into book (name) values (book_name) returning id
      )
      insert into book_genre_rel (genre_id, book_id) 
        select genre.id, book.id from genre, book
    $$
    

    这是一个测试它的例子:

    select insert_book_and_genre('how to win friends by writing good sql', 'self-help')
    

    现在,如果您已经创建了该函数(在 Supabase 查询编辑器中),那么您可以像这样从客户端调用它:

    const { data, error } = await supabase
      .rpc('insert_book_and_genre', {book_name: 'how I became a millionaire at age 3', genre_name: 'lifestyle'})
    

    同样,我不推荐这种方法,至少对于genre 部分不推荐。您应该先插入您的流派(它们可能不会改变),然后将其简化为仅插入 bookbook_genre_rel 记录。

    【讨论】:

    • 完美,感谢您将我的用例拆开!
    • 我的荣幸。就个人而言,我使用的简单解决方案是第一个 - 只需根据需要进行多个客户端调用,然后您可以根据需要(非常快速)在客户端代码中进行调整。正如我所说,你最终会改变一些事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 2020-09-11
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    相关资源
    最近更新 更多