PostgreSQLで関数を書くとき、最初にぶつかるのがどうやって結果を返すかってことだよね。時には単純に数字1つ返したいだけ。時にはテーブル丸ごと返したいし、場合によっては複数のデータセットを返したいこともある。このセクションでは、基本的なパターン全部を解説するよ。シンプルなRETURNからRETURN QUERY、RETURNS TABLE、SETOFまで。
1つの結果:RETURN
もし関数が1つだけ値を返せばいいなら――例えば合計や行数とか――普通のRETURNを使えばOK。
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT;
BEGIN
SELECT COUNT(*) INTO total FROM students;
RETURN total;
END;
$$ LANGUAGE plpgsql;
PL/pgSQLで関数を作るときは、何を返すかをちゃんと指定しないといけない。これはRETURNSキーワードで決めるんだ。関数が返す「フォーマット」を定義する感じ。だから数字1つでも、テキストでも、データのテーブルでも、全部RETURNSの行で書く必要があるよ。
シンプルな例:
CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
RETURN a + b;
END;
$$ LANGUAGE plpgsql;
ここでRETURNS INTって書いてあるのは、この関数が数字を返すって意味だよ。
1つの値を返す
まずは一番シンプルなやつから――1つの値を返す関数。例えば、studentsテーブルの学生数を数える関数:
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT;
BEGIN
SELECT COUNT(*) INTO total FROM students; -- クエリの結果をtotal変数に保存
RETURN total; -- 結果を返す
END;
$$ LANGUAGE plpgsql;
この関数はこうやって呼び出せる:
SELECT count_students(); -- 学生の数を返す
RETURNS TABLEで複数の値を返す
1つじゃなくて、複数のレコードを返したいときもあるよね。例えば、全学生の名前とIDのリストとか。そういうときはRETURNS TABLE構文を使う。
CREATE FUNCTION get_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT id, name FROM students; -- クエリの結果をテーブルとして返す
END;
$$ LANGUAGE plpgsql;
この関数もこうやって呼び出せる:
SELECT * FROM get_students(); -- 全学生のテーブルを返す
RETURNS TABLEってキーワードに注目してね。これは関数が指定したカラム(この場合はidとname)のテーブルを返すって意味だよ。
RETURN QUERYの使い方
さっきの例、もう気に入ったかもだけど、もう1つポイントがある。RETURN QUERYはPL/pgSQLの魔法みたいなやつで、クエリの結果をそのまま返せるんだ。これを使えば、クエリ全体でも一部でも返せるよ。
例えば、データベースでactive = TRUEになってる、今アクティブな学生だけ返したい場合:
CREATE FUNCTION get_active_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE active = TRUE; -- アクティブな学生だけ返す
END;
$$ LANGUAGE plpgsql;
この関数を呼び出すと、アクティブな学生のデータが取れる:
SELECT * FROM get_active_students();
RETURNS TABLEなしで複数行を返す
場合によっては、RETURNS TABLEを使わずにデータの行を返したいこともある。そんなときはSETOF型を使う。これで同じ構造のデータ行を返せるよ。 例えば:
CREATE FUNCTION get_student_names() RETURNS SETOF TEXT AS $$
BEGIN
RETURN QUERY
SELECT name
FROM students;
END;
$$ LANGUAGE plpgsql;
この関数は学生の名前だけのリストを返す:
SELECT * FROM get_student_names();
入力データによって返す値を変える
関数はいつも静的な結果だけ返すわけじゃない。パラメータを使って、動的に結果を変えることもできる。
例えば、学生IDでデータを返す例:
CREATE FUNCTION get_student_by_id(student_id INT) RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE id = student_id; -- student_idパラメータを使う
END;
$$ LANGUAGE plpgsql;
これで特定の学生の情報を取得できる:
SELECT * FROM get_student_by_id(3); -- ID=3の学生データを返す
複雑なデータ(複数セット)を返す
データがもっと複雑で、複数のセットで返したい場合もある。そんなときはカーソルを使うこともできる。例えば、関数からアクティブな学生と非アクティブな学生の2つのデータセットを返したい場合。
CREATE FUNCTION get_students_status() RETURNS SETOF RECORD AS $$
BEGIN
RETURN QUERY
SELECT id, name, 'active' AS status
FROM students
WHERE active = TRUE;
RETURN QUERY
SELECT id, name, 'inactive' AS status
FROM students
WHERE active = FALSE;
END;
$$ LANGUAGE plpgsql;
これで両方のデータセットを取得できる:
SELECT * FROM get_students_status();
RETURNSでよくあるミス
戻り値の型を指定しない: 何を返すか指定しないと、PostgreSQLはエラーを出す。例えば:
CREATE FUNCTION no_return_type() AS $$ -- エラー、RETURNSが指定されてない
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
データ型が合ってない:返す値が宣言した型と合ってるか確認しよう。例えばINTを返すって書いてるのに、文字列を返そうとしたらダメ。
RETURN QUERYの使い忘れ: 複雑なクエリでRETURN QUERYを忘れると、関数は何も返さないよ。
複数値返却のミス: データの行を返すのにSETOFやTABLEを使い忘れると、PostgreSQLはエラーを出す。
GO TO FULL VERSION