関数引数PL / PGSQLとしてレコードを渡す
-
13-12-2019 - |
質問
最初の私はPL / PGSQLに本当に新しいです。プロジェクトに必要です。
私はこの(簡素化された)問題で立ち往生しています。
My DBスキーマには、NからM関係があります(著者、書籍、Author_books)
今PL / PSGSQL関数挿入_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、出版社、...)のすべてのフィールドを介して行かなければならず、それらを声明に挿入に追加するか、「よりスマートな」方法がありますか?
質問3 :私の関数insert_bookをどのように呼びますか?私はここでこの例を見つけました(http://dbaspot.com/postgresql/206142passing-record-function-Argument-pl-pgsql.html)。しかし、それは本当に私を助けません。テスト目的のために私はシェルを使用していますが、後でJDBCでJavaを使用します。
あなたの助けをありがとうございました。
解決
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 FIDDLE。
あなたの質問に関して:
質問1:関数の概要「正しい」/それは理にかなっていますか?
は、複合型book
の代わりに基本タイプを渡すのが簡単な場合がありますが、完全に有効なアプローチです。ただし、複雑な種類のために構文のまわりであなたの道を知る必要があります。たとえば、マイ例の名前の周囲の括弧内に注意してください.(x._book).*
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:録画帳をテーブルブックに挿入する方法? (...)または「よりスマートな」方法はありますか?
スマートな方法は、Composite Typeを(variable_name).*
で分解することです。
type がtable
(ITから派生されている)と一致することが保証されているので、これはまれな場合の1つです。永続コードのINSERT
コマンドの列リスト。
質問3:私の関数挿入_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;
.