你大概已經不只一次聽過「陣列」這個詞了。在不同的程式語言裡,陣列的意思其實差不多,但還是有些小細節。
在 PostgreSQL 裡,陣列是一種資料型別,可以讓你在一個資料表的欄位裡存放一組同型別的值。就像你不是只放一筆資料,而是把一整「箱」資料塞進一個儲存格。這可以是數字、字串、日期,甚至更複雜的物件。
如果用抽象一點的說法,陣列就像一個工具箱。你不用把每一把鑰匙都拿在手上(每把鑰匙像一個欄位/列),而是把它們都丟進一個方便的箱子裡(單一欄位,裡面是陣列)。
建立陣列的兩種方式
在 PostgreSQL 裡有兩種主要的陣列語法。就像打包行李有兩種方法——結果一樣,但做法不太一樣:
- 用大括號
{}的語法
這是比較簡潔、常見的寫法:
-- 字串陣列
'{"蘋果", "香蕉", "櫻桃"}'
-- 數字陣列
'{1, 2, 3, 4, 5}'
-- 日期陣列
'{"2023-01-01", "2023-01-02", "2023-01-03"}'
- 用建構子
ARRAY[]的語法
這種寫法比較明確、可讀性高:
-- 字串陣列
ARRAY['蘋果', '香蕉', '櫻桃']
-- 數字陣列
ARRAY[1, 2, 3, 4, 5]
-- 日期陣列
ARRAY['2023-01-01'::DATE, '2023-01-02'::DATE, '2023-01-03'::DATE]
這兩種語法其實都一樣好用!你要用哪一種就看你自己習慣或當下情境。就像在其他程式語言裡 for 跟 while 迴圈一樣——功能上沒差,但有時候某一種寫法比較順手。
什麼時候該用陣列
陣列是 PostgreSQL 的超能力,特別適合那些不想為了某些資料再多開一張表或多加一個欄位的情境。它們很適合:
- 儲存清單、標籤或分類
想像一下我們要做一個電商網站的資料庫。每個商品可能有好幾個標籤,例如:
- 對於 T 恤來說,標籤可能是:
["服飾", "男生", "運動"]。 - 對於耳機來說,標籤可能是:
["電子產品", "無線", "小玩意"]。
用陣列的話,你可以直接把這些標籤存在同一個欄位,不用另外開一張標籤表,省空間又讓資料結構更簡單。
-- 有標籤陣列的商品表
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
tags TEXT[] -- 標籤的字串陣列
);
-- 範例資料
INSERT INTO products (name, tags)
VALUES
('T 恤', ARRAY['服飾', '男生', '運動']),
('耳機', ARRAY['電子產品', '無線', '小玩意']);
- 儲存訂單清單
如果你在處理訂單,陣列可以幫你把一張訂單裡的商品清單都存起來:
-- 有商品 ID 陣列的訂單表
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name TEXT,
product_ids INTEGER[] -- 商品 ID 的陣列
);
-- 範例資料
INSERT INTO orders (customer_name, product_ids)
VALUES
('安娜', ARRAY[1, 2, 3]),
('奧托', ARRAY[4, 5]);
這樣每張訂單就有一個商品清單,超方便對吧?
簡單的設定或偏好
如果你要存一些簡單的設定清單或使用者偏好:
CREATE TABLE user_preferences ( user_id INTEGER PRIMARY KEY, notification_types TEXT[], allowed_days INTEGER[] -- 星期幾:1-7 );
陣列跟其他資料型別的比較
這裡要記得,陣列只是 PostgreSQL 工具箱裡的另一個工具,不是每個情境都適合用。比如說,陣列的替代方案可以是關聯表(多對多關係),或是用 JSON/JSONB 型別。
陣列 vs JSONB
陣列很適合你已經確定要存一組同型別的值時。它們比較簡單、速度快、佔空間也小。
JSONB則適合你要存比較複雜、結構彈性的物件。不過 JSONB 處理起來會比較麻煩一點。
同一組資料用陣列跟 JSONB 的範例:
-- 陣列
ARRAY['服飾', '男生', '運動']
-- JSONB
'["服飾", "男生", "運動"]'::JSONB
如果你常常要做排序、篩選或建立索引這種操作,陣列會是更好的選擇。
實戰中用陣列的範例
來看個情境:你要做一個大學點名系統。每堂課有一個學生清單,但我們不想另外開一張表來連結學生跟課程。這時就可以用陣列:
-- 有學生陣列的課程表
CREATE TABLE lectures (
id SERIAL PRIMARY KEY,
topic TEXT NOT NULL,
students INTEGER[] -- 學生 ID 的陣列
);
-- 範例資料
INSERT INTO lectures (topic, students)
VALUES
('資料庫', ARRAY[101, 102, 103]),
('演算法', ARRAY[104, 105]);
這樣你就可以很輕鬆查詢每堂課的學生清單,也可以直接在陣列裡加或刪學生。
在 PostgreSQL 用陣列時要注意的事
- 陣列裡的資料型別要一致。 PostgreSQL 不允許你在同一個陣列裡混用字串跟數字。
-- OK
ARRAY[1, 2, 3] -- 數字陣列
-- 錯誤:混用字串跟數字
ARRAY['蘋果', 42, '櫻桃']
- 陣列的索引從 1 開始,不是從 0。這點要注意,因為很多程式語言(像 Python、JavaScript、C++ 等)都是從 0 開始。
- 支援 NULL:陣列裡可以有 NULL 值
- 多維度:PostgreSQL 支援多維陣列
GO TO FULL VERSION