Chắc là bạn đã nghe về mảng kha khá lần rồi. Trong các ngôn ngữ lập trình khác nhau thì nó cũng gần giống nhau thôi. Nhưng vẫn có vài điểm khác biệt nho nhỏ.
Mảng trong PostgreSQL là một kiểu dữ liệu cho phép lưu một tập giá trị cùng kiểu trong một cột của bảng. Kiểu như bạn không chỉ ghi một giá trị, mà là cả một "hộp" dữ liệu vào một ô. Có thể là danh sách số, chuỗi, ngày tháng hoặc thậm chí là các object phức tạp hơn.
Nói kiểu trừu tượng thì mảng giống như một hộp đựng đồ nghề. Thay vì cầm cả bộ chìa khóa trên tay (mỗi chìa là một cột/hàng riêng), bạn bỏ hết vào một cái vali gọn gàng (một cột chứa mảng).
Hai cách tạo mảng
Trong PostgreSQL có hai cú pháp chính để tạo mảng. Kiểu như hai cách khác nhau để đóng gói vali — kết quả như nhau, chỉ là cách làm khác thôi:
- Cú pháp dùng ngoặc nhọn
{}
Đây là cách gọn và hay dùng nhất:
-- Mảng chuỗi
'{"tao", "chuoi", "anh dao"}'
-- Mảng số
'{1, 2, 3, 4, 5}'
-- Mảng ngày tháng
'{"2023-01-01", "2023-01-02", "2023-01-03"}'
- Cú pháp dùng constructor
ARRAY[]
Cách này rõ ràng và dễ đọc hơn:
-- Mảng chuỗi
ARRAY['tao', 'chuoi', 'anh dao']
-- Mảng số
ARRAY[1, 2, 3, 4, 5]
-- Mảng ngày tháng
ARRAY['2023-01-01'::DATE, '2023-01-02'::DATE, '2023-01-03'::DATE]
cả hai cú pháp đều hoạt động như nhau! Chọn cái nào là tùy bạn và hoàn cảnh sử dụng. Kiểu như chọn giữa vòng lặp for và while trong các ngôn ngữ lập trình khác — về chức năng thì như nhau, nhưng có cái sẽ tiện hơn trong từng trường hợp cụ thể.
Khi nào nên dùng mảng
Mảng là siêu năng lực của PostgreSQL, giúp giải quyết các bài toán mà tạo thêm bảng hay cột mới thì hơi phiền. Nó cực hợp cho:
- Lưu danh sách, tag hoặc category
Giả sử bạn đang tạo database cho một shop online. Mỗi sản phẩm có thể có nhiều tag, ví dụ:
- Với áo thun thì tag có thể là:
["quan ao", "nam", "the thao"]. - Với tai nghe thì tag là:
["dien tu", "khong day", "gadget"].
Dùng mảng, bạn có thể lưu các tag này trong một cột, không cần tạo bảng riêng cho tag, tiết kiệm chỗ và đơn giản hóa cấu trúc dữ liệu.
-- Bảng sản phẩm với mảng tag
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
tags TEXT[] -- Mảng chuỗi cho tag
);
-- Ví dụ dữ liệu
INSERT INTO products (name, tags)
VALUES
('Ao thun', ARRAY['quan ao', 'nam', 'the thao']),
('Tai nghe', ARRAY['dien tu', 'khong day', 'gadget']);
- Lưu danh sách đơn hàng
Nếu bạn làm việc với đơn hàng, mảng có thể giúp lưu danh sách sản phẩm trong một đơn:
-- Bảng đơn hàng với mảng ID sản phẩm
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name TEXT,
product_ids INTEGER[] -- Mảng id sản phẩm
);
-- Ví dụ dữ liệu
INSERT INTO orders (customer_name, product_ids)
VALUES
('Anna', ARRAY[1, 2, 3]),
('Otto', ARRAY[4, 5]);
Giờ mỗi đơn hàng có danh sách sản phẩm đã mua. Tiện ghê đúng không?
Các cấu hình và cài đặt đơn giản
Khi cần lưu các danh sách cài đặt hoặc sở thích đơn giản của user:
CREATE TABLE user_preferences ( user_id INTEGER PRIMARY KEY, notification_types TEXT[], allowed_days INTEGER[] -- các ngày trong tuần: 1-7 );
So sánh mảng với các kiểu dữ liệu khác
Điều quan trọng là hiểu mảng chỉ là một công cụ nữa trong kho PostgreSQL, không phải lúc nào cũng hợp lý. Ví dụ, thay vì mảng, bạn có thể dùng bảng liên kết (quan hệ "nhiều-nhiều") hoặc kiểu dữ liệu JSON/JSONB.
Mảng vs JSONB
Mảng rất tiện khi bạn chắc chắn sẽ lưu nhiều giá trị cùng kiểu. Nó đơn giản, nhanh và tốn ít dung lượng.
JSONB hợp cho các cấu trúc phức tạp hơn, ví dụ cần lưu object với cấu trúc linh hoạt. Nhưng JSONB thì xử lý sẽ phức tạp hơn.
Ví dụ mảng và JSONB cho cùng một bộ dữ liệu:
-- Mảng
ARRAY['quan ao', 'nam', 'the thao']
-- JSONB
'["quan ao", "nam", "the thao"]'::JSONB
Nếu bạn hay phải làm các thao tác như sort, filter hoặc index, mảng sẽ là lựa chọn tốt hơn.
Ví dụ dùng mảng trong bài toán thực tế
Giả sử bạn đang phát triển app điểm danh ở trường đại học. Mỗi buổi học có danh sách sinh viên đã tham dự, nhưng không cần tạo bảng riêng để liên kết sinh viên với buổi học. Thay vào đó, dùng mảng luôn:
-- Bảng buổi học với mảng sinh viên
CREATE TABLE lectures (
id SERIAL PRIMARY KEY,
topic TEXT NOT NULL,
students INTEGER[] -- Mảng id sinh viên
);
-- Ví dụ dữ liệu
INSERT INTO lectures (topic, students)
VALUES
('Co so du lieu', ARRAY[101, 102, 103]),
('Thuat toan', ARRAY[104, 105]);
Giờ bạn dễ dàng truy vấn danh sách sinh viên cho bất kỳ buổi học nào, cũng như thêm/xóa sinh viên khỏi mảng.
Lưu ý khi dùng mảng trong PostgreSQL
- Kiểu dữ liệu trong mảng phải đồng nhất. PostgreSQL không cho phép trộn, ví dụ, chuỗi và số trong cùng một mảng.
-- Được
ARRAY[1, 2, 3] -- Mảng số
-- Lỗi: trộn chuỗi và số
ARRAY['tao', 42, 'anh dao']
- Chỉ số của phần tử trong mảng bắt đầu từ 1, không phải 0. Đừng quên nếu bạn quen với các ngôn ngữ mà index bắt đầu từ 0 (Python, JavaScript, C++,...).
- Hỗ trợ NULL: mảng có thể chứa giá trị NULL
- Mảng nhiều chiều: PostgreSQL hỗ trợ mảng nhiều chiều
GO TO FULL VERSION