CodeGym /コース /SQL SELF /PL/pgSQLで関数から値を返す方法

PL/pgSQLで関数から値を返す方法

SQL SELF
レベル 50, レッスン 1
使用可能

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はエラーを出す。

2
タスク
SQL SELF, レベル 50, レッスン 1
ロック未解除
アクティブな学生をフィルタリングする関数
アクティブな学生をフィルタリングする関数
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION