首先我对 pl/pgsql 真的很陌生。一个项目需要它。

我被这个(简化的)问题困扰。

我的数据库模式具有 n 对 m 关系(作者、书籍、author_books)

现在我想要一个 pl/psgsql 函数 insert_book。(我确实知道所有作者肯定已经在作者表中,所以我只想传递他们的主键)。

这个功能大纲就是我想到的。

 create or replace function insert_book(book_to_insert book, authors integer[])
  returns void as $$
begin
    -- insert book into table books
    -- for each author add an entry to author_books table
end;
 $$ language plpgsql;

作为论据,我想传递一份类型书籍的记录和编写它的作者。但这究竟是如何运作的呢?我用谷歌搜索了很多,似乎无法弄清楚这一点......

问题1:功能大纲是否“正确”/有意义吗?

问题2:如何将记录簿插入表格簿?我是否必须遍历书籍的所有字段(标题、isbn、出版商...)并将它们添加到 INSERT INTO 语句中,还是有“更智能”的方法?

问题3:我如何调用我的函数 insert_book?我在这里找到了这个例子(http://dbaspot.com/postgresql/206142-passing-record-function-argument-pl-pgsql.html),但这并没有真正帮助我。出于测试目的,我使用 shell,但稍后我们将使用 Java 和 JDBC。

非常感谢您的帮助。

有帮助吗?

解决方案

使用 unnest() 和一个 数据修改CTE (需要 Postgres 9.1 或更高版本),这可以是一个简单的 SQL 查询:

WITH x AS (SELECT '(1,foo_book)'::book AS _book
                , '{1,2,3}'::int[]     AS _authors)
   , y AS (
   INSERT INTO book  -- no column list, correct due to composite type
   SELECT (x._book).*
   FROM   x
   RETURNING book_id
   )
INSERT INTO author_book (book_id, author_id)
SELECT y.book_id, unnest(x._authors)
FROM   x,y;  -- CROSS JOIN ok, only 1 row for x and y

第一个 CTE x 只是为了简化数据输入,并不是严格需要的。

SQL 小提琴。

至于你的问题:

问题一:功能大纲是否“正确”/有意义吗?

传递基本类型而不是复合类型可能更容易 book, ,但这是一个完全有效的方法。不过,您必须了解复杂类型的语法。例如,请注意我的示例中名称周围的括号: (x._book).*.

A plpgsql 函数 可能看起来像这样:

CREATE OR REPLACE FUNCTION f_insert_book(_book book, _authors integer[])
   RETURNS void AS 
$func$
BEGIN
    WITH y AS (
        INSERT INTO book b
        SELECT (_book).*
        RETURNING b.book_id
        )
    INSERT INTO author_book (book_id, author_id)
    SELECT y.book_id, unnest(_authors)
    FROM   y;
END
$func$ LANGUAGE plpgsql;

问题2:如何将记录簿插入表格簿?(...)或者有“更聪明”的方法吗?

更聪明的方法是分解复合类型 (variable_name).*.

作为 类型 保证匹配 table (源自它),这是极少数情况之一,完全没问题, 不是 提供列列表 INSERT 持久化代码中的命令。

问题3:我如何调用我的函数 insert_book?...

SELECT f_insert_book('(1,foo_book)'::book, '{1,2,3}'::int[]);

在其他 plpgsql 函数中,使用 PERFORM 代替 SELECT 如果您不提供目标(INTO foo) 对于(不存在的)结果。

其他提示

通过JSON数据类型(PostgreSQL 9.2或更高版本):

CREATE OR REPLACE FUNCTION f_insert_book(_book json, _authors json)
   RETURNS void AS 
$$
BEGIN
-- insert book into table books
Insert into books values select * from json_populate_recordset(null:book, _book);
    -- for each author add an entry to author_books table
Insert into authors values select * from json_populate_recordset(null:authors, _authors);
end;
$$ language plpgsql;
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top