Bài 18: Thực hành xác định cấu trúc bảng và các trường khoá

I. Lý thuyết trọng tâm

1. Xem xét bài toán

Xét bài toán quản lí các bản thu âm nhạc cho một website âm nhạc. Mỗi bản thu âm cần lưu trữ các thông tin: tên bản nhạc, nhạc sĩ sáng tác và ca sĩ thể hiện.

Trước khi đi vào thực hành, cần nắm rõ một số quy ước: khi nói đến nhạc sĩ sáng tác bản nhạc là nói đến tên một nhạc sĩ hay tên một nhóm nhạc sĩ sáng tác bản nhạc đó. Tương tự, khi nói đến tên một ca sĩ là nói đến tên một ca sĩ hay một nhóm ca sĩ biểu diễn tác phẩm.

Dưới đây là ví dụ về một bản ghi chép thông tin các bản thu âm:

STT Tên bản nhạc Tên nhạc sĩ Tên ca sĩ
1 Du kích Sông Thao Đỗ Nhuận Doãn Tần
2 Trường ca Sông Lô Văn Cao Lê Dung
3 Tình ca Hoàng Việt Trần Khánh
4 Xa khơi Nguyễn Tài Tuệ Tân Nhàn
5 Việt Nam quê hương tôi Đỗ Nhuận Quốc Hương
6 Tiến về Hà Nội Văn Cao Doãn Tần
7 Nhạc rừng Hoàng Việt Quốc Hương
8 Tiếng hát giữa rừng Pác Bó Nguyễn Tài Tuệ Lê Dung
9 Trường ca Sông Lô Văn Cao Trần Khánh
10 Tiến về Hà Nội Văn Cao Quốc Hương

Nhìn vào Bảng 18.1, có thể rút ra một số nhận xét: bản nhạc “Trường ca Sông Lô” có hai bản thu âm (dòng 2 và 9), bản nhạc “Tiến về Hà Nội” cũng có hai bản thu âm (dòng 6 và 10). Nhạc sĩ Văn Cao có nhiều bản nhạc được thu âm nhất (4 bản thu âm ở dòng 2, 6, 9, 10). Ca sĩ Lê Dung thể hiện 2 bản thu âm (dòng 2 và 8).

2. Xác định cấu trúc bảng ban đầu

Tổng hợp tất cả các thông tin cần quản lí, ta viết ra thành dãy: số hiệu bản thu âm (STT), tên bản nhạc, tên nhạc sĩ sáng tác, tên ca sĩ thể hiện. Từ đó có thể hình dung về một bảng dữ liệu tên là banthuam, với các trường dữ liệu có tên gọi cụ thể:

banthuam(idBanthuam, tenBannhac, tenNhacsi, tenCasi)

Trong đó:

  • idBanthuam: số hiệu bản thu âm – xác định duy nhất mỗi bản thu âm nên được chọn làm khoá chính (gạch chân).
  • tenBannhac: tên bản nhạc.
  • tenNhacsi: tên nhạc sĩ sáng tác.
  • tenCasi: tên ca sĩ thể hiện.

Nhóm ba trường (tenBannhac, tenNhacsi, tenCasi) cũng có thể xác định duy nhất một bản thu âm, nhưng dùng idBanthuam làm khoá chính sẽ ngắn gọn và thuận tiện hơn.

3. Tổ chức lại bảng dữ liệu

Nếu giữ nguyên cấu trúc một bảng duy nhất như trên, dữ liệu sẽ bị lặp lại rất nhiều. Ví dụ, một ca sĩ thể hiện nhiều bản nhạc khác nhau thì tên ca sĩ bị lặp ở nhiều dòng, gây lãng phí dung lượng lưu trữ và khó khăn khi cần sửa chữa. Chẳng hạn, ca sĩ Trần Khánh thể hiện ở dòng 3 và 9 – nếu cần sửa tên ca sĩ, phải tìm và sửa ở tất cả các dòng có tên đó. Nếu sửa thiếu một dòng, dữ liệu sẽ mất tính nhất quán.

Để khắc phục, ta phân tích và sắp xếp lại bằng cách tách dữ liệu lặp ra thành bảng riêng.

Bước 1: Tách bảng ca sĩ

Lập bảng casi(idCasi, tenCasi) với trường khoá là idCasi, và thay trường tenCasi trong bảng banthuam bằng idCasi. Khi đó, idCasi trong bảng banthuam trở thành khoá ngoài tham chiếu đến khoá chính idCasi trong bảng casi.

idCasi tenCasi
1 Trần Khánh
2 Lê Dung
3 Tân Nhân
4 Quốc Hương
5 Doãn Tần

Bảng banthuam sau khi thay tenCasi bằng idCasi:

idBanthuam tenBannhac tenNhacsi idCasi
1 Du kích Sông Thao Đỗ Nhuận 5
2 Trường ca Sông Lô Văn Cao 2
3 Tình ca Hoàng Việt 1
4 Xa khơi Nguyễn Tài Tuệ 3
5 Việt Nam quê hương tôi Đỗ Nhuận 4
6 Tiến về Hà Nội Văn Cao 5
7 Nhạc rừng Hoàng Việt 4
8 Tiếng hát giữa rừng Pác Bó Nguyễn Tài Tuệ 2
9 Trường ca Sông Lô Văn Cao 1
10 Tiến về Hà Nội Văn Cao 4

Bước 2: Tách bảng bản nhạc

Tương tự, một bản nhạc có thể có nhiều bản thu âm khác nhau do những ca sĩ khác nhau thể hiện (ví dụ bản nhạc “Trường ca Sông Lô” xuất hiện ở dòng 2 và 9). Vì vậy ta tạo bảng bannhac(idBannhac, tenBannhac, tenNhacsi) với trường khoá là idBannhac, và thay cặp (tenBannhac, tenNhacsi) trong bảng banthuam bằng idBannhac.

Cấu trúc lúc này gồm ba bảng:

  • banthuam(idBanthuam, idBannhac, idCasi)
  • casi(idCasi, tenCasi)
  • bannhac(idBannhac, tenBannhac, tenNhacsi)
idBannhac tenBannhac tenNhacsi
1 Du kích Sông Thao Đỗ Nhuận
2 Trường ca Sông Lô Văn Cao
3 Tình ca Hoàng Việt
4 Xa khơi Nguyễn Tài Tuệ
5 Việt Nam quê hương tôi Đỗ Nhuận
6 Tiến về Hà Nội Văn Cao
7 Nhạc rừng Hoàng Việt
8 Tiếng hát giữa rừng Pác Bó Nguyễn Tài Tuệ

 

idBanthuam idBannhac idCasi
1 1 5
2 2 2
3 3 1
4 4 3
5 5 4
6 6 5
7 7 4
8 8 2
9 2 1
10 6 4

Bước 3: Tách bảng nhạc sĩ

Tên nhạc sĩ trong bảng bannhac vẫn bị lặp lại do một nhạc sĩ có thể sáng tác nhiều bản nhạc. Ví dụ, nhạc sĩ Văn Cao xuất hiện ở dòng 2 và 6 trong Bảng 18.4. Vì vậy ta lập bảng nhacsi(idNhacsi, tenNhacsi) và thay trường tenNhacsi trong bảng bannhac bằng idNhacsi.

idNhacsi tenNhacsi
1 Đỗ Nhuận
2 Văn Cao
3 Hoàng Việt
4 Nguyễn Tài Tuệ

 

idBannhac tenBannhac idNhacsi
1 Du kích Sông Thao 1
2 Trường ca Sông Lô 2
3 Tình ca 3
4 Xa khơi 4
5 Việt Nam quê hương tôi 1
6 Tiến về Hà Nội 2
7 Nhạc rừng 3
8 Tiếng hát giữa rừng Pác Bó 4

Kết quả: Cơ sở dữ liệu gồm 4 bảng

Sau quá trình tổ chức lại, cơ sở dữ liệu thu được gồm bốn bảng:

  • casi(idCasi, tenCasi)
  • nhacsi(idNhacsi, tenNhacsi)
  • bannhac(idBannhac, tenBannhac, idNhacsi)
  • banthuam(idBanthuam, idBannhac, idCasi)

4. Các loại khoá

Sau khi tổ chức lại, mỗi bảng đều có một khoá chính (tên trường được gạch chân), dùng để xác định duy nhất mỗi bản ghi trong bảng.

Khoá ngoài của các bảng:

  • Bảng bannhac: trường idNhacsi là khoá ngoài, tham chiếu đến khoá chính idNhacsi trong bảng nhacsi.
  • Bảng banthuam: trường idBannhac là khoá ngoài tham chiếu đến khoá chính idBannhac trong bảng bannhac; trường idCasi là khoá ngoài tham chiếu đến khoá chính idCasi trong bảng casi.

Khoá cấm trùng lặp giá trị (Unique): Ngoài khoá chính, một số cặp trường cũng không được phép trùng lặp giá trị:

  • Trong bảng bannhac: cặp (tenBannhac, idNhacsi) không được trùng lặp, vì một nhạc sĩ không thể sáng tác hai bản nhạc cùng tên.
  • Trong bảng banthuam: cặp (idBannhac, idCasi) không được trùng lặp, vì một ca sĩ không thu âm cùng một bản nhạc hai lần.

Các cặp trường này phải được đặt khoá cấm trùng lặp (Unique).

5. Kiểu dữ liệu của các trường

Để đơn giản, kiểu dữ liệu của các trường được chọn như sau:

  • Các trường khoá chính (idCasi, idNhacsi, idBannhac, idBanthuam): kiểu số nguyên INT và tự động tăng giá trị AUTO_INCREMENT khi thêm bản ghi mới.
  • Các trường khoá ngoài (idNhacsi trong bảng bannhac, idBannhac và idCasi trong bảng banthuam): kiểu số nguyên INT.
  • Các trường tên (tenCasi, tenNhacsi, tenBannhac): kiểu xâu kí tự có độ dài tối đa 255 kí tự VARCHAR(255).

II. Hướng dẫn giải bài tập SGK

Bài 1 (Luyện tập)

Đề bài: Có thể có những nhạc sĩ, ca sĩ trùng tên nên người ta muốn quản lí thêm thông tin ngày sinh của các nhạc sĩ, ca sĩ. Để làm được việc đó, CSDL cần thay đổi như thế nào?

Lời giải:

Khi cần quản lí thêm ngày sinh để phân biệt nhạc sĩ hoặc ca sĩ trùng tên, ta chỉ cần thêm một trường mới vào bảng tương ứng:

  • Bảng casi thêm trường ngaySinh: casi(idCasi, tenCasi, ngaySinh)
  • Bảng nhacsi thêm trường ngaySinh: nhacsi(idNhacsi, tenNhacsi, ngaySinh)

Trường ngaySinh có thể chọn kiểu dữ liệu DATE.

Các bảng bannhacbanthuam không cần thay đổi, vì chúng liên kết với ca sĩ và nhạc sĩ thông qua các trường khoá (idCasi, idNhacsi) chứ không phụ thuộc vào tên. Nhờ đã tổ chức CSDL thành nhiều bảng riêng biệt, việc bổ sung thông tin chỉ ảnh hưởng đến đúng bảng chứa thông tin cần thêm mà không làm thay đổi cấu trúc các bảng còn lại.

Bài 2 (Luyện tập)

Đề bài: Nếu muốn quản lí thêm thông tin nơi sinh của nhạc sĩ, ca sĩ (tên tỉnh/thành phố), CSDL cần thay đổi như thế nào?

Lời giải:

Tương tự Bài 1, ta thêm trường noiSinh vào bảng casi và nhacsi:

  • casi(idCasi, tenCasi, noiSinh)
  • nhacsi(idNhacsi, tenNhacsi, noiSinh)

Trường noiSinh có thể chọn kiểu dữ liệu VARCHAR(255) để lưu tên tỉnh/thành phố.

Tuy nhiên, nếu muốn quản lí chặt chẽ hơn và tránh lặp tên tỉnh/thành phố, có thể tạo thêm một bảng riêng tinhtp(idTinhtp, tenTinhtp) và sử dụng trường idTinhtp làm khoá ngoài trong bảng casi và nhacsi thay cho noiSinh:

  • casi(idCasi, tenCasi, idTinhtp)
  • nhacsi(idNhacsi, tenNhacsi, idTinhtp)

Cách làm này áp dụng đúng nguyên tắc tách dữ liệu lặp đã thực hành trong bài học.

Bài Vận dụng

Đề bài: Thực hiện các bước phân tích để thiết lập mô hình dữ liệu cho một bài toán quản lí thực tế, ví dụ quản lí danh sách tên quận/huyện của các tỉnh/thành phố.

Lời giải:

Bước 1 – Xem xét bài toán: Cần quản lí danh sách tên quận/huyện của các tỉnh/thành phố. Mỗi quận/huyện thuộc về đúng một tỉnh/thành phố, nhưng một tỉnh/thành phố có thể có nhiều quận/huyện.

Bước 2 – Xác định cấu trúc bảng ban đầu: Liệt kê các dữ liệu cần lưu trữ thành một bảng duy nhất:

quanhuyen_ds(idQuanhuyen, tenQuanhuyen, tenTinhtp)

Bước 3 – Tổ chức lại bảng dữ liệu: Tên tỉnh/thành phố bị lặp lại nhiều lần (vì mỗi tỉnh có nhiều quận/huyện). Áp dụng nguyên tắc tách dữ liệu lặp, ta tạo bảng riêng cho tỉnh/thành phố:

  • tinhtp(idTinhtp, tenTinhtp)
  • quanhuyen(idQuanhuyen, tenQuanhuyen, idTinhtp)

Bước 4 – Xác định các loại khoá:

  • Khoá chính: idTinhtp (bảng tinhtp), idQuanhuyen (bảng quanhuyen).
  • Khoá ngoài: idTinhtp trong bảng quanhuyen tham chiếu đến idTinhtp trong bảng tinhtp.
  • Khoá cấm trùng lặp: cặp (tenQuanhuyen, idTinhtp) trong bảng quanhuyen không được trùng, vì trong cùng một tỉnh không thể có hai quận/huyện cùng tên.

Bước 5 – Kiểu dữ liệu:

  • idTinhtp, idQuanhuyen: INT, AUTO_INCREMENT.
  • idTinhtp (khoá ngoài trong bảng quanhuyen): INT.
  • tenTinhtp, tenQuanhuyen: VARCHAR(255).

Ví dụ minh hoạ dữ liệu:

Bảng tinhtp:

idTinhtp tenTinhtp
1 Hà Nội
2 TP. Hồ Chí Minh
3 Đà Nẵng

Bảng quanhuyen:

idQuanhuyen tenQuanhuyen idTinhtp
1 Ba Đình 1
2 Hoàn Kiếm 1
3 Quận 1 2
4 Hải Châu 3
Thầy Phạm Thành Danh

Thầy Phạm Thành Danh

(Người kiểm duyệt, ra đề)

Chức vụ: Trưởng ban biên soạn môn Tin Học THPT

Trình độ: Cử nhân Sư phạm Tin học, Chứng chỉ hạng II, Chứng chỉ Tin học, Ngoại ngữ B1

Kinh nghiệm: 8+ năm kinh nghiệm tại Trường THPT Thuận Hóa