従来のSQLは、1つのセルに複数の値を格納することを想定していません。リレーショナルモデルは正規化を要求します。しかし、現代の問題では「タグリスト」や「評価スケール」などのフィールドが頻繁に見られ、特定の行のレベルで複数の値を操作することが便利です。一部のDBMS(PostgreSQL、Oracle)は、ARRAY型や類似のメカニズムを提供しています。
配列を使用することは、正規化の原則に違反し、多くの操作(フィルタリング、更新、インデックス作成)を困難にし、DBMS間でのコードの移植性を低下させます。しかし、キャッシュや小さな値リストの高速検索などの理由で便利または避けられない場合があります。
CREATE TABLE products ( id SERIAL PRIMARY KEY, tags TEXT[] ); -- 挿入: INSERT INTO products(tags) VALUES (ARRAY['eco','sale','hot']); -- 配列を基に検索: SELECT * FROM products WHERE 'eco' = ANY (tags);
主な特徴:
配列の個々の要素にインデックスを付けることはできますか?
PostgreSQLでは、はい、GIN/GISTインデックスを通じて可能です:
CREATE INDEX idx_tags ON products USING GIN (tags);
区切り文字で文字列列の配列内の値の存在を迅速に確認するにはどうすればよいですか?
SQLは標準でできませんが、パターン検索を使用します:
SELECT * FROM users WHERE ',admin,' like concat('%,',role,',%');
しかし、このアプローチは信頼性が低く、遅いです。
配列にどれだけの値を格納でき、何が制限していますか?
制限はDBMSによります。例えば、PostgreSQLでは文字列のサイズ(1〜2 MB)のみ制限があります。
eコマースプロジェクトで商品タグをカンマ区切りの文字列として1つの列に保存することにしました。タグによる商品の迅速な検索が非常に困難になり、フィルタリングのエラーが発生し、解析エラーのためにタグの重複が発生しました。
利点:
欠点:
PostgreSQLでは、小さくて変更されないセット(ユーザーロール)にARRAYとGINインデックスを使用しました。大きい場合は、ロール用の別のテーブルを使用しました。
利点:
欠点: