First I am really new to pl/pgsql. Need it for a project.
I am stuck with this (simplified) problem.
My db schema has a n to m relationship (author, books, author_books)
Now I want to have a pl/psgsql function insert_book. (I do know that all authors are definitely already in the author table, so I just want to pass their primary keys).
This function outline is what I have in mind.
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;
As arguments I thought to pass a record of type book and the authors that wrote it. But how exactly would this work? I googled quite a bit and can’t seem to figure this out…
Question 1: Is the function outline “correct”/does it make sense?
Question 2: How to insert record book into table book? Do I have to go over all fields of book (title, isbn, publisher,…) and add them to an INSERT INTO statement or is there a “smarter” way?
Question 3: How would I call my function insert_book? I found this example here (http://dbaspot.com/postgresql/206142-passing-record-function-argument-pl-pgsql.html), but that doesn’t really help me. For testing purposes I am using the shell, but later on we will use Java with JDBC.
Thank you very much for your help.
Using
unnest()and a data-modifying CTE (requires Postgres 9.1 or later), this can be a simple SQL query:The first CTE
xis just for simplified data input and not strictly needed.SQL Fiddle.
As to your questions:
Might be easier to pass base types instead of the composite type
book, but it is a perfectly valid approach. You have to know your way around the syntax for complex types, though. For instance, note the parenthesis around the name in my example:(x._book).*.A plpgsql function could look like this:
The smarter way is to decompose the composite type with
(variable_name).*.As the type is guaranteed to match the
table(being derived from it), this is one of the rare cases, where it is perfectly ok, not to provide a column list for theINSERTcommand in persisted code.Within other plpgsql functions, use
PERFORMinstead ofSELECTif you don’t provide a target (INTO foo) for the (non-existing) results.