Domanda

Prima sono davvero nuovo di pl/pgsql.Bisogno per un progetto.

Io sono bloccato con questo (semplificato) problema.

Il mio db schema n a m rapporto (autore, libri, author_books)

Ora voglio avere una pl/psgsql funzione insert_book.(So che tutti gli autori sono sicuramente già autore di tabella, quindi, voglio solo passare loro le chiavi primarie).

Questa funzione, il contorno è quello che ho in mente.

 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;

Come argomento ho pensato di passare un record di tipo di libro e gli autori che ha scritto.Ma esattamente come si farebbe questo lavoro?Ho googlato un po ' e non riesco a capire...

Domanda 1:È la funzione di contorno "corretto"non ha senso?

Domanda 2:Come inserire record di libro in libro?Devo andare su tutti i campi del libro (titolo, isbn, editore,...) e aggiungere un'istruzione INSERT INTO o c'è un "intelligenti" a modo?

Domanda 3:Come posso chiamare la mia funzione insert_book?Ho trovato questo esempio qui (http://dbaspot.com/postgresql/206142-passing-record-function-argument-pl-pgsql.html), ma che in realtà non mi aiutano.Per scopi di test sto usando la shell, ma più tardi ci sarà l'utilizzo di Java JDBC.

La ringrazio molto per il vostro aiuto.

È stato utile?

Soluzione

Utilizzando unnest() e un dati-modifica CTE (richiede Postgres 9.1 o versione successiva), questo può essere una semplice query 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

Il primo CTE x è solo per semplificare l'immissione dei dati e non sia strettamente necessario.

SQL Violino.

In quanto alle tue domande:

Domanda 1:È la funzione di contorno "corretto"non ha senso?

Potrebbe essere più facile passare i tipi di base invece di tipo composito book, ma è perfettamente valido approccio.È necessario conoscere il modo per aggirare la sintassi per tipi complessi, però.Per esempio, nota le parentesi intorno al nome nel mio esempio: (x._book).*.

Un plpgsql funzione potrebbe assomigliare a questo:

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;

Domanda 2:Come inserire record di libro in libro?(...) o c'è una "intelligenti" a modo?

Il modo più efficace è quello di scomporre il tipo composito con (variable_name).*.

Come tipo è garantito per abbinare il table (derivato da esso), questo è uno dei rari casi in cui è perfettamente ok, non per fornire un elenco di colonne per la INSERT comando persistente codice.

Domanda 3:Come posso chiamare la mia funzione insert_book?...

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

All'interno di altri plpgsql funzioni, utilizzare PERFORM invece di SELECT se non si fornisce un bersaglio (INTO foo) per la (non esistente) risultati.

Altri suggerimenti

Passando JSON tipo di dati (Postgresql 9.2 o superiore):

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top