Column には基本的には配列を入れない方がいいが、入れることはできる

RDB の原則として、Column には配列を入れない方がほとんど全てのケースで正しい選択になりますが、原理上は配列を入れることができます。

今回は RDB の Column 内での Array の扱い方を学びます。

RDB の原則の再確認

Array について学ぶ前に、まずは RDB の原則を再確認します。

例えばある記事に関して、複数のカテゴリーが紐付けることができるケースがあるとしましょう。

Fetchしてきたときの構造
const articles = [
  {
    id: 1,
    title: "this is react",
    category: ['react', 'js'],
  },
  {
    id: 2,
    title: "this is Emotion",
    category: ['CSS in JS', 'CSS'],
  },
];

こういう値を取得したいからといってテーブルを以下のように設計しては基本原則としていけません。(自分は RDB の専門家ではないので詳しくはないのですが、これに反した設計が許されるケースの一つは、検索用のテーブルがあります。あくまで検索だけために使い、データを保持する目的でない場合には許容されるケースがあります。他にも目的によっては許容されるのですが、おそらくはどれもデータを保存するための目的ではない、ということが共通点としてあるように思われます。)

これはよくない設計
create table articles
(
    id       serial,
    title    text,
    category text[] -- 配列を入れようとしているのはダメ
);

insert into articles(title, category)
VALUES ('this is react', ARRAY ['react', 'js']);

select * from articles;

なぜこれが良くないかというとことは、専門家が無限に説明してくださっているので参考書籍でご確認ください笑

ただ直感的にいって、配列をこんなところにねじ込むのは気持ち悪いし、もっと他にいい方法があるだろうということはエンジニアであればわかると思います。

ではどうするか。

以下のように二つのテーブルを作り、これを共通する article_id を架け橋にして関連づけます。これが RDB 的な正しい設計です。

正しいテーブル設計
create table articles
(
    id       serial,
    title    text
);

create table categories
(
    id       serial,
    article_id integer,
    title    text
);

ということで、様々な書籍が警鐘をならしている重要事項であり、私が説明するまでもないことではありますが、配列を column に入れる説明をするにあたって、誤解があってはいけないと思い、再度説明させていただきました。

あらためてどうやって配列を表現するか

あえて配列をcolumnに入れる設計
create table articles
(
    id       serial,
    title    text,
    category text[] -- あえて配列を入れる
);

-- array [] を使うパターン
insert into articles(title, category)
VALUES ('this is react', ARRAY ['react', 'js']);

-- {,} を使うパターン
insert into articles(title, category)
VALUES ('this is react', '{10000, 10000, 10000, 10000}');

select * from articles;

array を入れるためには ARRAY ['react', 'js'] のパターンと '{10000, 10000, 10000, 10000}' のパターンがあります。この例ではどちらも同じ結果になります。JS エンジニア的には前者が理解しやすいと思うのですが、PGDB の表記としては後者が一般的なようです。例えば select 文を実行した際に現れるのは後者の表現です。

Screen Shot 2020-08-05 at 16.52.00

オブジェクトのように一見見えますが、これが PGDB における array 表現の標準形です。

array 表記に慣れよう

繰り返しになりますが array を column には基本的に追加してはいけません。それは RDB の基本的な設計原則に反しているからです。

しかし、表現としては読める必要があり、扱える必要があります。

これは今後扱う array_aggjson_agg を理解する基礎となります。