Giới thiệu MariaDB & Thiết lập Cơ sở dữ liệu

Tại sao cần Cơ sở dữ liệu quan hệ? Ôn lại SQL

Vấn đề với lưu trữ trong bộ nhớ

Trong Bài 2 và 3, chúng ta lưu dữ liệu trong HashMapArrayList của Java. Điều này hoạt động cho việc học, nhưng có lỗi nghiêm trọng: tất cả dữ liệu mất khi ứng dụng khởi động lại. Hãy thử — dừng ứng dụng Spring Boot, khởi động lại, và tất cả bài viết và người dùng bạn đã tạo đều biến mất.

Cơ sở dữ liệu giải quyết điều này bằng cách lưu dữ liệu bền vững trên đĩa. Dù ứng dụng bị crash, server khởi động lại, hay bạn triển khai phiên bản mới, dữ liệu vẫn tồn tại.

Tại sao Cơ sở dữ liệu quan hệ?

Có hai loại chính:

Cơ sở dữ liệu quan hệ (SQL) lưu dữ liệu trong bảng với hàng và cột, giống bảng tính. Các bảng có thể liên kết qua quan hệ. Ví dụ: MariaDB, PostgreSQL, MySQL, Oracle, SQL Server.

Cơ sở dữ liệu phi quan hệ (NoSQL) lưu dữ liệu ở nhiều định dạng — tài liệu (MongoDB), cặp key-value (Redis), đồ thị (Neo4j), hoặc cột (Cassandra).

Cho ứng dụng blog, cơ sở dữ liệu quan hệ là lựa chọn tự nhiên vì:

  • Dữ liệu blog có cấu trúc cao — bài viết có tiêu đề, nội dung, tác giả, ngày tháng. Chúng phù hợp gọn gàng với cột bảng.
  • Quan hệ xuất hiện khắp nơi — người dùng có nhiều bài viết, bài viết có nhiều bình luận. Cơ sở dữ liệu quan hệ được xây dựng cho điều này.
  • Tính toàn vẹn dữ liệu quan trọng — bạn không muốn bình luận trỏ đến bài viết không tồn tại. Cơ sở dữ liệu quan hệ thực thi các quy tắc này bằng khóa ngoại (foreign key).
  • SQL là kỹ năng phổ quát — học một lần cho phép bạn làm việc với bất kỳ cơ sở dữ liệu quan hệ nào.

Tổng quan MariaDB — Lịch sử, Tính năng, Tương thích MySQL

Câu chuyện MariaDB

MariaDB có nguồn gốc thú vị. Năm 1995, Michael “Monty” Widenius đồng sáng tạo MySQL, trở thành cơ sở dữ liệu mã nguồn mở phổ biến nhất thế giới. Năm 2008, Sun Microsystems mua lại MySQL. Năm 2010, Oracle mua lại Sun Microsystems — và cùng với nó, MySQL.

Nhiều người trong cộng đồng mã nguồn mở lo ngại về sự quản lý MySQL của Oracle. Vì vậy Monty fork MySQL và tạo ra MariaDB năm 2009, đặt tên theo con gái nhỏ Maria (MySQL được đặt theo con gái lớn My).

MariaDB là fork được cộng đồng phát triển từ MySQL. Nó được thiết kế để thay thế hoàn toàn — nghĩa là bạn có thể chuyển từ MySQL sang MariaDB với ít hoặc không cần thay đổi code.

Tại sao MariaDB cho Series này?

  • Tương thích MySQL: Hầu hết tutorial, công cụ, và driver MySQL đều hoạt động với MariaDB.
  • Mã nguồn mở thực sự: MariaDB phát hành dưới giấy phép GPL không có hạn chế thương mại từ Oracle.
  • Hiệu suất: MariaDB bao gồm tối ưu hóa và storage engine không có trong MySQL.
  • Phát triển tích cực: MariaDB thường có tính năng mới trước MySQL.
  • Được ngành công nghiệp sử dụng: MariaDB được Wikipedia, Google, Samsung sử dụng.

Cài đặt MariaDB (Local & Docker)

Lựa chọn A: Docker (Khuyến nghị)

Docker là cách dễ nhất và sạch nhất để chạy MariaDB.

# Kéo image MariaDB chính thức và khởi động container
docker run --name blogdb \
  -e MARIADB_ROOT_PASSWORD=rootpass \
  -e MARIADB_DATABASE=blogdb \
  -e MARIADB_USER=bloguser \
  -e MARIADB_PASSWORD=blogpass \
  -p 3306:3306 \
  -d mariadb:11

Phân tích từng cờ:

  • --name blogdb — Đặt tên container “blogdb” để tham chiếu dễ dàng.
  • -e MARIADB_ROOT_PASSWORD=rootpass — Đặt mật khẩu root (admin). Trong production, dùng mật khẩu mạnh.
  • -e MARIADB_DATABASE=blogdb — Tự động tạo database “blogdb” khi khởi động lần đầu.
  • -e MARIADB_USER=bloguser — Tạo user non-root “bloguser.”
  • -e MARIADB_PASSWORD=blogpass — Đặt mật khẩu cho bloguser.
  • -p 3306:3306 — Ánh xạ cổng 3306 trên máy bạn đến cổng 3306 trong container.
  • -d — Chạy container ở chế độ nền.
  • mariadb:11 — Sử dụng image MariaDB phiên bản 11.

Kết nối vào MariaDB:

docker exec -it blogdb mariadb -u bloguser -pblogpass blogdb

Docker Compose (tùy chọn, thuận tiện hơn):

version: '3.8'
services:
  mariadb:
    image: mariadb:11
    container_name: blogdb
    environment:
      MARIADB_ROOT_PASSWORD: rootpass
      MARIADB_DATABASE: blogdb
      MARIADB_USER: bloguser
      MARIADB_PASSWORD: blogpass
    ports:
      - "3306:3306"
    volumes:
      - mariadb_data:/var/lib/mysql

volumes:
  mariadb_data:

Phần volumes đảm bảo dữ liệu tồn tại ngay cả khi container bị xóa.

Lựa chọn B: Cài đặt trực tiếp

macOS (Homebrew):

brew install mariadb
brew services start mariadb
mariadb-secure-installation

Linux (Ubuntu/Debian):

sudo apt update
sudo apt install mariadb-server
sudo systemctl start mariadb
sudo mariadb-secure-installation

Quản trị MariaDB cơ bản — User, Quyền, Database

Quản lý Database

-- Hiển thị tất cả database
SHOW DATABASES;

-- Tạo database mới
CREATE DATABASE blogdb
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

Giải thích bộ ký tự:

  • utf8mb4 — Hỗ trợ tất cả ký tự Unicode, bao gồm emoji. Luôn dùng thay vì utf8 (chỉ hỗ trợ ký tự 3-byte, không lưu được emoji).
  • utf8mb4_unicode_ci — Collation không phân biệt hoa thường. ci viết tắt của “case insensitive.”

Quản lý User

Trong production, ứng dụng không bao giờ nên kết nối bằng root. Tạo user chuyên dụng với quyền hạn chế.

-- Tạo user
CREATE USER 'bloguser'@'%' IDENTIFIED BY 'blogpass';

-- Cấp quyền trên database blogdb
GRANT ALL PRIVILEGES ON blogdb.* TO 'bloguser'@'%';
FLUSH PRIVILEGES;

'bloguser'@'%'% có nghĩa “bất kỳ host nào” (user có thể kết nối từ mọi nơi).

Nguyên tắc Quyền tối thiểu

Một nguyên tắc bảo mật quan trọng: chỉ cấp cho mỗi user những quyền họ cần, không hơn.

  • User root chỉ dùng cho quản trị (tạo database, tạo user).
  • User ứng dụng (bloguser) chỉ nên có quyền cần thiết để chạy app (SELECT, INSERT, UPDATE, DELETE).
  • User báo cáo chỉ đọc chỉ nên có quyền SELECT.

Ôn lại SQL thiết yếu (CREATE, INSERT, SELECT, UPDATE, DELETE, JOIN)

CREATE TABLE

CREATE TABLE authors (
    id          BIGINT       AUTO_INCREMENT PRIMARY KEY,
    name        VARCHAR(100) NOT NULL,
    email       VARCHAR(255) NOT NULL UNIQUE,
    bio         TEXT,
    created_at  TIMESTAMP    DEFAULT CURRENT_TIMESTAMP
);

Mỗi định nghĩa cột có cấu trúc: tên_cột KIỂU_DỮ_LIỆU RÀNG_BUỘC

  • BIGINT — Kiểu số nguyên lớn, phù hợp cho ID.
  • AUTO_INCREMENT — MariaDB tự động gán số tiếp theo (1, 2, 3…).
  • PRIMARY KEY — Xác định duy nhất mỗi hàng. Không trùng lặp, không NULL.
  • VARCHAR(100) — Chuỗi có độ dài thay đổi, tối đa 100 ký tự.
  • NOT NULL — Cột này phải có giá trị.
  • UNIQUE — Không hai hàng nào có cùng giá trị trong cột này.
  • TEXT — Chuỗi không giới hạn độ dài thực tế (tối đa 65,535 ký tự).

INSERT

INSERT INTO authors (name, email, bio) VALUES
    ('Alice Johnson', 'alice@example.com', 'Kỹ sư phần mềm và blogger'),
    ('Bob Smith', 'bob@example.com', 'Lập trình viên full-stack'),
    ('Carol Davis', 'carol@example.com', 'Chuyên gia database');

SELECT

-- Chọn tất cả
SELECT * FROM authors;

-- Lọc với WHERE
SELECT * FROM authors WHERE name = 'Alice Johnson';

-- Tìm kiếm mẫu với LIKE
SELECT * FROM authors WHERE email LIKE '%example.com';

-- Sắp xếp
SELECT * FROM authors ORDER BY name ASC;

-- Giới hạn kết quả (phân trang)
SELECT * FROM authors ORDER BY id LIMIT 10 OFFSET 20;

-- Đếm
SELECT COUNT(*) AS total_authors FROM authors;

UPDATE

-- Cập nhật hàng cụ thể
UPDATE authors SET bio = 'Kỹ sư phần mềm cấp cao' WHERE id = 1;

-- QUAN TRỌNG: Luôn dùng WHERE với UPDATE!
-- Không có WHERE, TẤT CẢ hàng sẽ bị cập nhật!

DELETE

-- Xóa hàng cụ thể
DELETE FROM authors WHERE id = 4;

-- QUAN TRỌNG: Luôn dùng WHERE với DELETE!

JOIN — Kết hợp bảng

-- Tạo bảng thứ hai
CREATE TABLE articles (
    id          BIGINT       AUTO_INCREMENT PRIMARY KEY,
    title       VARCHAR(255) NOT NULL,
    content     TEXT         NOT NULL,
    author_id   BIGINT       NOT NULL,
    created_at  TIMESTAMP    DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (author_id) REFERENCES authors(id)
);

-- INNER JOIN: Lấy bài viết với thông tin tác giả
SELECT 
    a.title       AS article_title,
    au.name       AS author_name,
    au.email      AS author_email
FROM articles a
INNER JOIN authors au ON a.author_id = au.id;

-- LEFT JOIN: Lấy TẤT CẢ tác giả, kể cả những người chưa có bài viết
SELECT au.name, a.title
FROM authors au
LEFT JOIN articles a ON au.id = a.author_id;

-- GROUP BY với COUNT: Mỗi tác giả viết bao nhiêu bài?
SELECT au.name, COUNT(a.id) AS article_count
FROM authors au
LEFT JOIN articles a ON au.id = a.author_id
GROUP BY au.id, au.name
ORDER BY article_count DESC;

Tóm tắt các kiểu JOIN

Kiểu JOIN Trả về
INNER JOIN Chỉ hàng khớp ở cả hai bảng
LEFT JOIN Tất cả hàng từ bảng trái + khớp từ bảng phải (NULL nếu không khớp)
RIGHT JOIN Tất cả hàng từ bảng phải + khớp từ bảng trái
CROSS JOIN Mọi tổ hợp hàng từ cả hai bảng (ít khi dùng)

Thực tế, INNER JOINLEFT JOIN đáp ứng 95% trường hợp.


Kiểu dữ liệu trong MariaDB

Kiểu số nguyên

Kiểu Lưu trữ Phạm vi
TINYINT 1 byte -128 đến 127
INT 4 bytes -2.1 tỷ đến 2.1 tỷ
BIGINT 8 bytes -9.2 quintillion đến 9.2 quintillion

Khuyến nghị: Dùng BIGINT cho khóa chính và khóa ngoại. Chênh lệch lưu trữ (8 byte vs 4 byte) không đáng kể.

Kiểu chuỗi

Kiểu Độ dài tối đa Trường hợp sử dụng
VARCHAR(n) 65,535 ký tự Chuỗi có độ dài thay đổi (tên, email, tiêu đề)
TEXT 65,535 ký tự Văn bản dài (nội dung bài viết)
MEDIUMTEXT 16 MB Văn bản rất dài

Kiểu ngày giờ

Kiểu Trường hợp sử dụng
DATE Ngày sinh, deadline
DATETIME Timestamp sự kiện (không có timezone)
TIMESTAMP Timestamp bản ghi (tự chuyển đổi UTC)

Khuyến nghị: Dùng TIMESTAMP cho cột created_atupdated_at.

Kiểu Boolean

MariaDB không có kiểu boolean thật. BOOLEAN là bí danh cho TINYINT(1):

is_active BOOLEAN DEFAULT TRUE
-- Tương đương: is_active TINYINT(1) DEFAULT 1
-- TRUE = 1, FALSE = 0

Kiểu số thập phân

-- DECIMAL cho tiền — LUÔN dùng cho dữ liệu tài chính
price DECIMAL(10, 2)  -- Tối đa: 99,999,999.99

-- KHÔNG BAO GIỜ dùng FLOAT hay DOUBLE cho tiền — chúng gây lỗi làm tròn!

Index và Khóa chính (Primary Key)

Index là gì?

Index là cấu trúc dữ liệu tăng tốc truy vấn dữ liệu. Không có index, MariaDB phải quét mọi hàng trong bảng (full table scan). Có index, nó có thể nhảy trực tiếp đến các hàng liên quan.

Phép so sánh là chỉ mục sách. Không có chỉ mục ở cuối sách, bạn phải đọc mọi trang để tìm thông tin về “Spring Boot.” Có chỉ mục, bạn tra cứu “Spring Boot,” tìm số trang, và đi thẳng đến đó.

Index kết hợp (Composite Index)

-- Nếu chúng ta thường lọc theo cả status VÀ category, index kết hợp giúp
CREATE INDEX idx_posts_status_category ON posts(status, category);

Thứ tự cột quan trọng trong index kết hợp. Index (status, category) tăng tốc truy vấn:

  • WHERE status = 'PUBLISHED' (dùng cột đầu)
  • WHERE status = 'PUBLISHED' AND category = 'TUTORIAL' (dùng cả hai)

Nhưng KHÔNG tăng tốc:

  • WHERE category = 'TUTORIAL' (không thể bỏ qua cột đầu)

Nghĩ như danh bạ sắp theo họ, rồi tên. Bạn có thể tra “Nguyễn” (chỉ họ) hoặc “Nguyễn Văn A” (cả hai), nhưng không thể hiệu quả tra chỉ “Văn A” (chỉ tên).

Khi nào thêm Index

Thêm index trên cột thường dùng trong:

  • Mệnh đề WHERE (lọc)
  • Điều kiện JOIN (khóa ngoại)
  • Mệnh đề ORDER BY (sắp xếp)

Nhưng KHÔNG thêm index trên mọi cột. Index tăng tốc đọc nhưng làm chậm ghi (mỗi INSERT, UPDATE, DELETE phải cập nhật index).


Giới thiệu Thiết kế Database — Chuẩn hóa cơ bản

Chuẩn hóa là gì?

Chuẩn hóa (normalization) là quá trình tổ chức database để giảm dư thừa và cải thiện toàn vẹn dữ liệu.

Dạng chuẩn 1 (1NF) — Không có nhóm lặp

-- ❌ VI PHẠM 1NF — tags lưu dưới dạng chuỗi phân cách bằng dấu phẩy
CREATE TABLE posts_bad (
    id BIGINT PRIMARY KEY,
    title VARCHAR(255),
    tags VARCHAR(500)    -- "java,spring,tutorial" — KHÔNG phải giá trị nguyên tử!
);

-- ✅ TUÂN THEO 1NF — tags lưu trong bảng riêng, mỗi tag một hàng
CREATE TABLE posts (id BIGINT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255));
CREATE TABLE post_tags (
    post_id BIGINT,
    tag     VARCHAR(50),
    PRIMARY KEY (post_id, tag),
    FOREIGN KEY (post_id) REFERENCES posts(id)
);

Dạng chuẩn 2 (2NF) và 3 (3NF)

  • 2NF: Mọi cột không khóa phụ thuộc vào toàn bộ khóa chính.
  • 3NF: Không có cột không khóa phụ thuộc vào cột không khóa khác.

Trong thực tế, bạn thường nhắm đến 3NF làm điểm khởi đầu. Tuy nhiên, đôi khi bạn cố tình giải chuẩn hóa (denormalize) để tăng hiệu suất — đây là đánh đổi mà chúng ta sẽ thảo luận trong Bài 16.


Sử dụng công cụ GUI (DBeaver / HeidiSQL)

DBeaver (Khuyến nghị — Đa nền tảng)

DBeaver là client database miễn phí, mã nguồn mở, hoạt động trên Windows, Mac, và Linux.

  1. Tải về từ dbeaver.io
  2. Nhấn New Database Connection → chọn MariaDB
  3. Điền: Host localhost, Port 3306, Database blogdb, Username bloguser, Password blogpass
  4. Nhấn Test ConnectionFinish

Thực hành: Thiết kế và tạo bảng cho ứng dụng Blog

Xác định thực thể và quan hệ

  • Users 1:N Posts (Một người dùng viết nhiều bài)
  • Posts 1:N Comments (Một bài viết có nhiều bình luận)
  • Posts N:1 Categories (Nhiều bài thuộc một danh mục)
  • Posts M:N Tags (Bài viết và tag nhiều-nhiều)

Tạo Schema

USE blogdb;

-- 1. BẢNG USERS
CREATE TABLE users (
    id              BIGINT          AUTO_INCREMENT PRIMARY KEY,
    username        VARCHAR(50)     NOT NULL,
    email           VARCHAR(255)    NOT NULL,
    password_hash   VARCHAR(255)    NOT NULL,
    full_name       VARCHAR(100),
    bio             TEXT,
    role            VARCHAR(20)     NOT NULL DEFAULT 'ROLE_USER',
    is_active       BOOLEAN         NOT NULL DEFAULT TRUE,
    created_at      TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP 
                                    ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE INDEX idx_users_username (username),
    UNIQUE INDEX idx_users_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 2. BẢNG CATEGORIES
CREATE TABLE categories (
    id          BIGINT          AUTO_INCREMENT PRIMARY KEY,
    name        VARCHAR(100)    NOT NULL,
    slug        VARCHAR(100)    NOT NULL,
    description TEXT,
    created_at  TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE INDEX idx_categories_name (name),
    UNIQUE INDEX idx_categories_slug (slug)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 3. BẢNG TAGS
CREATE TABLE tags (
    id          BIGINT          AUTO_INCREMENT PRIMARY KEY,
    name        VARCHAR(50)     NOT NULL,
    slug        VARCHAR(50)     NOT NULL,
    created_at  TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE INDEX idx_tags_name (name),
    UNIQUE INDEX idx_tags_slug (slug)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 4. BẢNG POSTS
CREATE TABLE posts (
    id              BIGINT          AUTO_INCREMENT PRIMARY KEY,
    title           VARCHAR(500)    NOT NULL,
    slug            VARCHAR(500)    NOT NULL,
    content         TEXT            NOT NULL,
    excerpt         VARCHAR(1000),
    status          VARCHAR(20)     NOT NULL DEFAULT 'DRAFT',
    author_id       BIGINT          NOT NULL,
    category_id     BIGINT,
    published_at    TIMESTAMP       NULL,
    created_at      TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP       NOT NULL DEFAULT CURRENT_TIMESTAMP 
                                    ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE INDEX idx_posts_slug (slug),
    INDEX idx_posts_status (status),
    INDEX idx_posts_author_id (author_id),
    -- RESTRICT: không cho xóa user nếu có bài viết
    FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE RESTRICT,
    -- SET NULL: nếu category bị xóa, đặt category_id thành NULL
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 5. BẢNG COMMENTS
CREATE TABLE comments (
    id          BIGINT      AUTO_INCREMENT PRIMARY KEY,
    content     TEXT        NOT NULL,
    post_id     BIGINT      NOT NULL,
    author_id   BIGINT      NOT NULL,
    parent_id   BIGINT      NULL,
    created_at  TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP 
                            ON UPDATE CURRENT_TIMESTAMP,
    -- CASCADE: nếu bài viết bị xóa, tất cả bình luận cũng bị xóa
    FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
    FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE RESTRICT,
    FOREIGN KEY (parent_id) REFERENCES comments(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 6. BẢNG POST_TAGS (bảng nối nhiều-nhiều)
CREATE TABLE post_tags (
    post_id     BIGINT NOT NULL,
    tag_id      BIGINT NOT NULL,
    PRIMARY KEY (post_id, tag_id),
    FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
    FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Hành động khóa ngoại

  • ON DELETE RESTRICT — Ngăn xóa hàng cha nếu có hàng con tồn tại.
  • ON DELETE SET NULL — Nếu hàng cha bị xóa, đặt khóa ngoại thành NULL.
  • ON DELETE CASCADE — Nếu hàng cha bị xóa, xóa tất cả hàng con.

Bài tập

  1. Thêm cột views_count INT (mặc định 0) vào bảng posts.
  2. Viết truy vấn “bài viết phổ biến nhất” theo số bình luận.
  3. Viết truy vấn “hoạt động gần đây” — 10 bình luận mới nhất với tiêu đề bài viết.
  4. Kiểm thử ràng buộc khóa ngoại: thử xóa user có bài viết, xóa category có bài viết.

Tổng kết

  • Cơ sở dữ liệu quan hệ: Lưu trữ bền vững, dữ liệu có cấu trúc, quan hệ qua khóa ngoại.
  • MariaDB: Fork mã nguồn mở từ MySQL, tương thích hoàn toàn, phát triển tích cực.
  • Docker: Cách sạch nhất để chạy MariaDB — một lệnh khởi động server đã cấu hình.
  • SQL thiết yếu: CREATE, INSERT, SELECT, UPDATE, DELETE, JOIN.
  • Kiểu dữ liệu: BIGINT cho ID, VARCHAR cho chuỗi, TEXT cho nội dung dài, TIMESTAMP cho ngày, DECIMAL cho tiền.
  • Index: Tăng tốc đọc nhưng chậm ghi. Index cột dùng trong WHERE, ORDER BY, JOIN.
  • Chuẩn hóa: Tổ chức bảng giảm dư thừa (1NF, 2NF, 3NF).
  • Schema blog: 6 bảng với quan hệ, ràng buộc, index, và dữ liệu mẫu.

Bài tiếp theo

Trong Bài 5, chúng ta sẽ kết nối Spring Boot với database MariaDB sử dụng Spring Data JPA và Hibernate.


Tham chiếu nhanh

Khái niệm Mô tả
CSDL quan hệ Lưu dữ liệu trong bảng với hàng và cột, liên kết bằng quan hệ
MariaDB Fork mã nguồn mở từ MySQL, tương thích, cộng đồng phát triển
SQL Ngôn ngữ truy vấn có cấu trúc — ngôn ngữ chuẩn cho CSDL quan hệ
PRIMARY KEY Xác định duy nhất mỗi hàng; tự động index
FOREIGN KEY Liên kết cột đến khóa chính của bảng khác
INDEX Cấu trúc dữ liệu tăng tốc truy vấn
JOIN Kết hợp hàng từ nhiều bảng dựa trên cột liên quan
Chuẩn hóa Tổ chức bảng giảm thiểu dư thừa (1NF, 2NF, 3NF)
ON DELETE CASCADE Xóa hàng con khi hàng cha bị xóa
ON DELETE RESTRICT Ngăn xóa hàng cha nếu có hàng con
utf8mb4 Bộ ký tự hỗ trợ toàn bộ Unicode bao gồm emoji

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *