1. ホーム
  2. sql

[解決済み] PL/pgSQLでPostgreSQLのレコードとして複数のフィールドを返す

2023-05-03 06:46:45

質問

PL/pgSQLを使用したSPを書いています。

私は、いくつかの異なるテーブルからのフィールドで構成されるレコードを返したいのです。以下のような感じです。

CREATE OR REPLACE FUNCTION get_object_fields(name text)
  RETURNS RECORD AS $$
BEGIN
  -- fetch fields f1, f2 and f3 from table t1
  -- fetch fields f4, f5 from table t2
  -- fetch fields f6, f7 and f8 from table t3
  -- return fields f1 ... f8 as a record
END
$$ language plpgsql; 

異なるテーブルのフィールドを1つのレコードのフィールドとして返すにはどうしたらよいでしょうか?

[編集]をクリックします。

私は、上であげた例が少し単純すぎることに気づきました。私が取得する必要があるフィールドのいくつかは、クエリされるデータベース テーブルの別の行として保存されますが、私はそれらを「フラット化された」レコード構造で返したいと思います。

以下のコードは、さらに説明するのに役立つはずです。

CREATE TABLE user (id int, school_id int, name varchar(32));

CREATE TYPE my_type AS (
  user1_id   int,
  user1_name varchar(32),
  user2_id   int,
  user2_name varchar(32)
);

CREATE OR REPLACE FUNCTION get_two_users_from_school(schoolid int)
  RETURNS my_type AS $$
DECLARE
  result my_type;
  temp_result user;
BEGIN
  -- for purpose of this question assume 2 rows returned
  SELECT id, name INTO temp_result FROM user where school_id = schoolid LIMIT 2;
  -- Will the (pseudo)code below work?:
  result.user1_id := temp_result[0].id ;
  result.user1_name := temp_result[0].name ;
  result.user2_id := temp_result[1].id ;
  result.user2_name := temp_result[1].name ;
  return result ;
END
$$ language plpgsql

どのように解決するのですか?

新しい型を定義し、その型を返すように関数を定義する必要があります。

CREATE TYPE my_type AS (f1 varchar(10), f2 varchar(10) /* , ... */ );

CREATE OR REPLACE FUNCTION get_object_fields(name text) 
RETURNS my_type 
AS 
$$

DECLARE
  result_record my_type;

BEGIN
  SELECT f1, f2, f3
  INTO result_record.f1, result_record.f2, result_record.f3
  FROM table1
  WHERE pk_col = 42;

  SELECT f3 
  INTO result_record.f3
  FROM table2
  WHERE pk_col = 24;

  RETURN result_record;

END
$$ LANGUAGE plpgsql; 

複数のレコードを返したい場合は、関数を以下のように定義する必要があります。 returns setof my_type


更新

もう一つの方法として RETURNS TABLE() を作成する代わりに TYPE を作成する代わりに、Postgres 8.4で導入された

CREATE OR REPLACE FUNCTION get_object_fields(name text) 
  RETURNS TABLE (f1 varchar(10), f2 varchar(10) /* , ... */ )
...