Bài 5 — Cài đặt PostgreSQL và nạp database mẫu¶
🎯 Học xong bài này, bạn sẽ
- Có một PostgreSQL 16 đang chạy thật trên máy của mình
- Hiểu mô hình máy khách – máy chủ và vì sao phải nhớ con số 5432
- Kết nối được bằng
psqlvà dùng thành thạo các lệnh meta\l,\dt,\d,\q - Nạp xong database
truong_hocvà tự kiểm tra được là đã nạp đúng - Tự gỡ được ba sự cố phổ biến nhất khi cài lần đầu
Đây là bài bản lề của cả khóa học
Bốn bài trước bạn chỉ đọc. Từ Bài 6 trở đi, mọi bài đều giả định rằng máy bạn đã có PostgreSQL chạy được và database truong_hoc đã nạp xong.
Đừng đi tiếp khi phần Tự kiểm tra ở cuối mục Thực hành chưa trả về đúng kết quả.
🧠 Câu chuyện mở đầu¶
Bốn bài vừa rồi giống hệt việc học luật giao thông trong lớp: bạn biết đèn đỏ là dừng, biết vạch kẻ để làm gì. Nhưng bạn chưa từng ngồi lên xe.
Hôm nay bạn ngồi lên xe.
Và cũng như lần đầu tập xe, sẽ có vài cú chết máy. Ba cú phổ biến nhất là thế này:
Bạn cài xong, gõ lệnh kết nối, màn hình trả về could not connect to server. Bạn tưởng mình cài hỏng — thật ra phần mềm chạy tốt, chỉ là bạn đang gõ cửa sai số nhà.
Bạn nhập mật khẩu, máy báo password authentication failed. Bạn chắc chắn mình gõ đúng — nhưng bạn đang gõ mật khẩu của người dùng hệ điều hành, còn PostgreSQL có hệ thống người dùng riêng của nó.
Bạn kết nối được, gõ SELECT * FROM hoc_sinh;, máy báo relation "hoc_sinh" does not exist. Bạn tưởng dữ liệu nạp hỏng — thật ra bạn đang đứng trong một database khác.
Cả ba đều không phải lỗi của bạn, và cả ba đều bắt nguồn từ một hiểu lầm duy nhất về cách PostgreSQL được tổ chức.
Câu hỏi của bài: hiểu lầm đó là gì?
📖 Khái niệm & thuật ngữ¶
PostgreSQL không phải một ứng dụng, mà là một máy chủ¶
Đây chính là hiểu lầm gốc rễ.
Word hay Excel là ứng dụng: bạn mở nó lên, làm việc, đóng lại. PostgreSQL thì khác hẳn. Nó là một máy chủ (server) — một chương trình chạy âm thầm và liên tục ở nền, kể cả khi bạn không nhìn thấy cửa sổ nào. Nó nằm đó chờ, ai gõ cửa thì phục vụ.
Chương trình gõ cửa gọi là máy khách (client). psql là một máy khách; pgAdmin là một máy khách; ứng dụng web bạn viết sau này cũng là một máy khách.
Mô hình này gọi là máy khách – máy chủ (client–server), và nó giải thích luôn hình vẽ về DBMS ở Bài 3: nhiều người kết nối cùng lúc vào một kho dữ liệu duy nhất, được một phần mềm canh gác.
Ba thứ bạn phải nói đúng khi gõ cửa¶
Vì máy chủ phục vụ nhiều người, mỗi lần kết nối bạn phải trả lời ba câu hỏi. Ba sự cố trong câu chuyện tương ứng chính xác với ba câu này:
1. Gõ cửa ở đâu? — máy nào, cổng (port) số mấy.
Một máy tính có thể chạy nhiều máy chủ cùng lúc (web, mail, database…). Cổng là con số để phân biệt chúng, như số phòng trong một toà nhà. PostgreSQL mặc định nằm ở cổng 5432. Gõ nhầm cổng thì đúng toà nhà nhưng sai phòng — và bạn nhận could not connect to server.
2. Bạn là ai? — tên vai trò (role) và mật khẩu.
PostgreSQL có hệ thống người dùng hoàn toàn riêng, không liên quan gì tới tài khoản đăng nhập máy tính của bạn. Mỗi người dùng trong PostgreSQL gọi là một vai trò; vai trò quản trị mặc định tên là postgres. Đó là lý do mật khẩu máy tính không dùng được ở đây.
3. Bạn muốn vào database nào?
Một máy chủ PostgreSQL quản lý nhiều database cùng lúc — tập hợp đó gọi là một cụm cơ sở dữ liệu (cluster). Sau khi cài, cụm đã có sẵn database postgres dùng cho việc quản trị. Database truong_hoc của chúng ta là một database khác, phải tạo thêm.
Quên nói tên database, bạn sẽ bị đưa vào database mặc định — và ở đó tất nhiên không có bảng hoc_sinh nào. Đó chính là sự cố thứ ba.
Câu thần chú để nhớ ba thứ
Ở đâu (máy + cổng 5432) · là ai (vai trò + mật khẩu) · vào đâu (tên database).
Gần như mọi lỗi kết nối bạn gặp trong đời đều là thiếu hoặc sai một trong ba thứ này.
psql và các lệnh meta¶
psql là máy khách dòng lệnh chính thức của PostgreSQL. Trong psql bạn gõ được hai loại câu, và phân biệt chúng rất dễ:
- Câu SQL — luôn kết thúc bằng dấu chấm phẩy
;. Đây là câu gửi tới máy chủ. - Lệnh meta (meta-command) — luôn bắt đầu bằng dấu sổ chéo ngược
\, không có dấu chấm phẩy. Đây là lệnh của riêngpsql, máy chủ không nhìn thấy.
Bốn lệnh meta bạn sẽ dùng hằng ngày:
| Lệnh | Viết tắt của | Làm gì |
|---|---|---|
\l |
list | Liệt kê mọi database trong cụm |
\dt |
describe tables | Liệt kê các bảng trong database hiện tại |
\d ten_bang |
describe | Mô tả một bảng: cột, kiểu, khoá, ràng buộc |
\q |
quit | Thoát psql |
Hai lệnh hữu ích nữa: \c ten_database để chuyển sang database khác mà không cần thoát ra, và \? để xem toàn bộ danh sách lệnh meta.
\dt và \d chính là từ điển dữ liệu
Nhớ Bài 3 chứ? \dt không có phép màu nào cả — nó chỉ là một câu SELECT dựng sẵn, chạy trên từ điển dữ liệu. Gõ \dt trong psql sau khi bật \set ECHO_HIDDEN on là bạn nhìn thấy câu SQL thật phía sau.
Bảng thuật ngữ¶
| Tiếng Việt | English | Nghĩa dễ hiểu |
|---|---|---|
| Máy chủ | server | Chương trình chạy ngầm liên tục, chờ phục vụ |
| Máy khách | client | Chương trình kết nối tới máy chủ để nhờ việc |
| Máy khách – máy chủ | client–server | Mô hình nhiều máy khách dùng chung một máy chủ |
| Cổng | port | Con số phân biệt các máy chủ trên cùng một máy; PostgreSQL là 5432 |
| Vai trò | role | Người dùng của PostgreSQL; mặc định có postgres |
| Cụm cơ sở dữ liệu | cluster | Tập các database do một máy chủ PostgreSQL quản lý |
| Lệnh meta | meta-command | Lệnh riêng của psql, bắt đầu bằng \, không có ; |
| Vùng chứa | container | Một "hộp" chạy sẵn phần mềm, độc lập với máy thật |
| Ảnh | image | Khuôn mẫu để tạo ra vùng chứa |
🖼️ Sơ đồ¶
Đường đi của một câu lệnh, từ ngón tay bạn tới ổ đĩa và quay về:
flowchart LR
subgraph MK["💻 MÁY KHÁCH"]
P["<b>psql</b><br/>hoặc pgAdmin<br/>hoặc ứng dụng web"]
end
subgraph MC["🖥️ MÁY CHỦ PostgreSQL — cổng 5432"]
direction TB
AUTH["<b>1. Xác thực</b><br/>vai trò + mật khẩu"]
PARSE["<b>2. Phân tích câu lệnh</b><br/>rồi tối ưu"]
EXEC["<b>3. Thực thi</b><br/>kiểm tra ràng buộc"]
AUTH --> PARSE --> EXEC
end
subgraph CUM["🗄️ CỤM CƠ SỞ DỮ LIỆU"]
direction TB
DB1[("postgres<br/><i>database quản trị</i>")]
DB2[("<b>truong_hoc</b><br/><i>10 bảng của khóa học</i>")]
end
P -->|"SELECT count* FROM hoc_sinh;"| AUTH
EXEC --> DB2
DB2 -.->|"kết quả: 40"| P
style MK fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style MC fill:#fff8e1,stroke:#f9a825,stroke-width:2px
style CUM fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
style DB2 fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px
Và đây là toàn bộ chặng đường của bài này, sáu bước:
flowchart TB
B1["<b>Bước 1</b><br/>Cài PostgreSQL 16<br/><i>Docker hoặc apt hoặc installer</i>"]
B2["<b>Bước 2</b><br/>Kết nối bằng psql<br/><i>ở đâu · là ai</i>"]
B3["<b>Bước 3</b><br/>Tạo database truong_hoc"]
B4["<b>Bước 4</b><br/>Tải dataset từ GitHub"]
B5["<b>Bước 5</b><br/>Nạp 02-chuan-hoa.sql"]
B6["<b>Bước 6</b><br/>✅ Tự kiểm tra<br/><i>hoc_sinh phải có 40 dòng</i>"]
B1 --> B2 --> B3 --> B4 --> B5 --> B6
style B1 fill:#e3f2fd,stroke:#1565c0
style B2 fill:#e3f2fd,stroke:#1565c0
style B3 fill:#fff8e1,stroke:#f9a825
style B4 fill:#fff8e1,stroke:#f9a825
style B5 fill:#fff8e1,stroke:#f9a825
style B6 fill:#c8e6c9,stroke:#1b5e20,stroke-width:3px
💻 Thực hành¶
Bước 1 — Cài PostgreSQL 16¶
Chọn một trong ba cách dưới đây. Không cần làm cả ba.
Cách này được khuyến nghị vì một lý do rất thực tế: nếu có gì hỏng, bạn xoá đi làm lại trong 30 giây mà máy tính không hề bị bẩn thêm một tệp nào.
Trước tiên cài Docker Desktop (Windows, macOS) hoặc Docker Engine (Linux). Kiểm tra đã cài được chưa:
Tạo và chạy một máy chủ PostgreSQL 16:
docker run -d \
--name pg-khoahoc \
-e POSTGRES_PASSWORD=hoc \
-e POSTGRES_DB=truong_hoc \
-p 5432:5432 \
-v pg-khoahoc-data:/var/lib/postgresql/data \
postgres:16
Đọc từng dòng để hiểu, đừng chép suông:
| Tham số | Nghĩa |
|---|---|
-d |
Chạy ngầm (detached), không chiếm cửa sổ dòng lệnh |
--name pg-khoahoc |
Đặt tên cho vùng chứa (container) — cái "hộp" chạy sẵn PostgreSQL, tách biệt hẳn với máy thật của bạn — để lát nữa gọi lại cho dễ |
-e POSTGRES_PASSWORD=hoc |
Mật khẩu của vai trò postgres là hoc |
-e POSTGRES_DB=truong_hoc |
Tạo sẵn luôn database truong_hoc — bỏ qua được Bước 3 |
-p 5432:5432 |
Nối cổng 5432 của máy bạn vào cổng 5432 trong vùng chứa |
-v pg-khoahoc-data:/... |
Giữ dữ liệu lại kể cả khi xoá vùng chứa |
postgres:16 |
Ảnh (image) cần dùng — khuôn mẫu để tạo ra vùng chứa; :16 là đúng phiên bản PostgreSQL của khóa học |
Kiểm tra đang chạy:
Cột STATUS phải hiện Up .... Nếu không thấy dòng nào, xem nhật ký để biết vì sao:
Hai lệnh dùng hằng ngày về sau — tắt máy rồi bật lại thì vùng chứa không tự chạy, bạn khởi động lại bằng:
Cách này cài thẳng vào máy, phù hợp nếu bạn dùng Linux và không muốn đụng tới Docker.
Nếu apt báo không tìm thấy gói postgresql-16
Kho phần mềm mặc định của bản Ubuntu bạn đang dùng có thể chứa phiên bản khác. Thêm kho chính thức của PostgreSQL rồi cài lại:
sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
--fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
| sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo apt install -y postgresql-16
Kiểm tra máy chủ đã chạy chưa:
Khi cài bằng apt, vai trò postgres chưa có mật khẩu. Đặt mật khẩu cho nó:
Giải thích: sudo -u postgres nghĩa là "chạy lệnh này với tư cách người dùng hệ điều hành tên postgres" — người dùng này được cài đặt tự động tạo ra và được phép vào thẳng, không cần mật khẩu.
Bật máy chủ tự chạy mỗi lần khởi động máy:
- Tải bộ cài từ postgresql.org/download/windows — chọn PostgreSQL 16.
- Chạy tệp
.exe. Ở màn hình Select Components, giữ nguyên các mục được chọn sẵn; đặc biệt phải cóCommand Line Tools— đó chính làpsql. - Màn hình Password: nhập mật khẩu cho vai trò
postgres. Khóa học này dùnghoc. Ghi lại mật khẩu đó — không có cách xem lại. - Màn hình Port: để nguyên
5432. - Màn hình Locale: chọn
Vietnamese, Vietnamhoặc để[Default locale]; cả hai đều chạy được. - Bấm Next cho tới khi cài xong. Có thể bỏ qua Stack Builder ở bước cuối.
Sau khi cài, mở SQL Shell (psql) từ Start Menu. Nó sẽ hỏi bốn thứ; cứ nhấn Enter để lấy giá trị mặc định trong ngoặc vuông, trừ mật khẩu:
Bước 2 — Kết nối bằng psql¶
docker exec -it pg-khoahoc nghĩa là "chạy lệnh sau đây bên trong vùng chứa tên pg-khoahoc". Nhờ vậy bạn không cần cài psql lên máy thật.
Ba chữ cái cần nhớ, chúng chính là "câu thần chú" ở trên:
| Tham số | Nghĩa | Ứng với |
|---|---|---|
-h và -p |
host, port | Ở đâu |
-U |
user | Là ai |
-d |
database | Vào đâu |
Kết nối thành công, dấu nhắc đổi thành tên database kèm dấu thăng:
Chào hỏi máy chủ một câu:
Rồi hỏi xem mình đang đứng ở đâu và là ai:
Hai câu này về sau sẽ cứu bạn rất nhiều lần — mỗi khi thấy "bảng không tồn tại", hãy gõ câu thứ hai trước tiên.
Bước 3 — Tạo database truong_hoc¶
Dùng Docker thì bỏ qua bước này
Tham số -e POSTGRES_DB=truong_hoc ở Bước 1 đã tạo sẵn rồi.
Với cách cài apt hoặc Windows, bạn đang ở trong database postgres. Tạo database mới:
ENCODING 'UTF8' là bắt buộc với khóa học này — dữ liệu có dấu tiếng Việt.
Rồi chuyển sang database vừa tạo bằng lệnh meta:
Dấu nhắc phải đổi thành truong_hoc=#. Nếu vẫn là postgres=# thì bạn đang đứng sai chỗ, và mọi bước sau sẽ thất bại.
Bước 4 — Tải dataset¶
Ba tệp dataset nằm trong thư mục dataset/ trên GitHub. Xem trang Database mẫu để biết mỗi tệp chứa gì.
Cách gọn nhất là tải cả kho về:
Không có git thì bấm nút Code → Download ZIP trên GitHub rồi giải nén.
Bước 5 — Nạp 02-chuan-hoa.sql¶
Bài này chỉ nạp một tệp: dataset/02-chuan-hoa.sql. Hai tệp còn lại để dành cho Cấp 2 và Cấp 4.
-v ON_ERROR_STOP=1 rất đáng nhớ: mặc định psql gặp lỗi vẫn chạy tiếp những câu sau, để lại một database nạp dở mà bạn không hay biết. Có tham số này, nó dừng ngay ở câu lỗi đầu tiên.
Màn hình sẽ trôi qua hàng loạt dòng DROP TABLE, CREATE TABLE, INSERT 0 40… Đó là bình thường.
Bước 6 — Tự kiểm tra¶
Đây là phần không được bỏ qua. Vào lại psql với database truong_hoc rồi làm ba việc sau.
Việc 1 — Đếm bảng. Gõ lệnh meta:
Phải hiện đúng 10 bảng: diem, diem_danh, giao_vien, hoc_sinh, lop, mon_hoc, muon_sach, phan_cong_day, phu_huynh, sach.
Việc 2 — Xem cấu trúc một bảng.
Bạn sẽ thấy 6 cột, khoá chính ma_hs, và một khoá ngoại (foreign key) trỏ tới bảng lop — đúng lời hứa "ma_lop chỉ được chứa mã lớp có thật" mà Bài 2 đã giới thiệu. Chính là lược đồ mà Bài 3 đã nói.
Việc 3 — Đếm dữ liệu. Câu quan trọng nhất của cả bài:
| so_hoc_sinh |
|---|
| 40 |
Nếu ra đúng 40, bạn đã xong. Chúc mừng — bạn vừa có một cơ sở dữ liệu thật đầu tiên trong đời.
Muốn chắc chắn hơn nữa, kiểm tra toàn bộ mười bảng một lần:
SELECT 'giao_vien' AS bang, count(*) AS so_dong FROM giao_vien
UNION ALL SELECT 'lop', count(*) FROM lop
UNION ALL SELECT 'hoc_sinh', count(*) FROM hoc_sinh
UNION ALL SELECT 'phu_huynh', count(*) FROM phu_huynh
UNION ALL SELECT 'mon_hoc', count(*) FROM mon_hoc
UNION ALL SELECT 'phan_cong_day', count(*) FROM phan_cong_day
UNION ALL SELECT 'diem', count(*) FROM diem
UNION ALL SELECT 'sach', count(*) FROM sach
UNION ALL SELECT 'muon_sach', count(*) FROM muon_sach
UNION ALL SELECT 'diem_danh', count(*) FROM diem_danh
ORDER BY bang;
Kết quả phải khớp chính xác bảng dưới đây:
| bang | so_dong |
|---|---|
| diem | 480 |
| diem_danh | 200 |
| giao_vien | 8 |
| hoc_sinh | 40 |
| lop | 6 |
| mon_hoc | 9 |
| muon_sach | 50 |
| phan_cong_day | 64 |
| phu_huynh | 45 |
| sach | 20 |
Lệch một con số nghĩa là tệp nạp chưa hết. Chạy lại Bước 5 — tệp 02-chuan-hoa.sql bắt đầu bằng DROP TABLE IF EXISTS nên nạp lại bao nhiêu lần cũng an toàn.
Cuối cùng, thoát ra:
Chạy thử một câu có ý nghĩa¶
Thưởng cho công sức vừa rồi — câu này trả lời một câu hỏi thật:
SELECT l.ten_lop, count(h.ma_hs) AS si_so
FROM lop l
JOIN hoc_sinh h ON h.ma_lop = l.ma_lop
GROUP BY l.ten_lop
ORDER BY l.ten_lop;
| ten_lop | si_so |
|---|---|
| 8A1 | 6 |
| 8A2 | 6 |
| 8A3 | 8 |
| 9A1 | 6 |
| 9A2 | 7 |
| 9A3 | 7 |
Chưa hiểu JOIN và GROUP BY cũng không sao — Bài 25 và Bài 27 sẽ dạy. Điều đáng nói là: câu hỏi mà lớp trưởng ở Bài 1 phải ngồi đếm cả buổi chiều, bây giờ bạn trả lời trong vài mili giây.
⚠️ Lỗi thường gặp¶
Lỗi 1: could not connect to server — cổng 5432 đã bị chiếm
Thông báo trên Linux thường là:
Còn Docker thì báo ngay khi docker run:
Error response from daemon: driver failed programming external connectivity on endpoint
pg-khoahoc: Bind for 0.0.0.0:5432 failed: port is already allocated
Nguyên nhân thường là một trong hai: máy chủ PostgreSQL chưa chạy, hoặc đã có một PostgreSQL khác (cài từ trước) đang chiếm cổng 5432.
Cách kiểm tra xem ai đang giữ cổng:
Cách sửa. Nếu chưa chạy thì bật lên:
Nếu đã có cái khác chiếm cổng, đơn giản nhất là dùng cổng khác cho vùng chứa của khóa học:
docker rm -f pg-khoahoc
docker run -d \
--name pg-khoahoc \
-e POSTGRES_PASSWORD=hoc \
-e POSTGRES_DB=truong_hoc \
-p 5433:5432 \
-v pg-khoahoc-data:/var/lib/postgresql/data \
postgres:16
Chỉ đúng một thứ đổi so với Bước 1: 5432:5432 thành 5433:5432 — nghĩa là máy bạn mở cổng 5433, còn bên trong vùng chứa PostgreSQL vẫn nằm ở 5432 như thường lệ. Dòng -v pg-khoahoc-data:... phải giữ nguyên, nếu không bạn sẽ mất phần dữ liệu bền vững mà Bước 1 đã thiết lập.
Từ đó về sau nhớ thêm -p 5433 vào mọi lệnh psql chạy từ máy thật.
Lỗi 2: password authentication failed — sai mật khẩu, hoặc nhầm hệ người dùng
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed:
FATAL: password authentication failed for user "postgres"
Nguyên nhân phổ biến nhất không phải gõ sai phím, mà là hiểu lầm đã nói ở phần Khái niệm: bạn đang gõ mật khẩu tài khoản máy tính, trong khi PostgreSQL có hệ thống vai trò riêng.
Cách sửa với Docker: mật khẩu là đúng cái bạn ghi ở POSTGRES_PASSWORD. Quên rồi thì xoá vùng chứa, tạo lại — chỉ mất 30 giây.
Cách sửa với apt: vào bằng người dùng hệ điều hành postgres (không cần mật khẩu) rồi đặt lại:
Cách sửa với Windows: không có cách xem lại mật khẩu cũ. Chạy lại bộ cài và chọn Repair, hoặc gỡ ra cài lại.
Một mẹo nhỏ để khỏi phải gõ mật khẩu mỗi lần — đặt biến môi trường trước khi chạy psql:
Biến này chỉ sống trong cửa sổ dòng lệnh hiện tại; đóng cửa sổ là mất.
Lỗi 3: relation ... does not exist — quên -d truong_hoc
Từ relation ở đây chính là "bảng" — nhớ Bài 4: trong mô hình quan hệ, bảng có tên toán học là relation.
Nguyên nhân: bạn đang đứng trong database postgres (database quản trị) chứ không phải truong_hoc. Quên -d truong_hoc là psql đưa bạn vào database trùng tên người dùng hoặc postgres.
Cách kiểm tra — gõ ngay câu này mỗi khi gặp lỗi trên:
Nếu nó trả về postgres thì bạn đã tìm ra thủ phạm.
Cách sửa: chuyển database ngay trong psql, không cần thoát ra:
Hoặc lần sau kết nối thì thêm -d truong_hoc.
Lỗi 4: Nạp tệp xong mà không có bảng nào
Triệu chứng: psql ... -f 02-chuan-hoa.sql chạy trôi qua, nhưng \dt báo Did not find any relations.
Nguyên nhân gần như luôn là: tệp đã được nạp vào database khác với database bạn đang mở để kiểm tra. Chuyện này xảy ra khi lệnh nạp thiếu -d truong_hoc.
Cách xác nhận: liệt kê mọi database rồi vào từng cái xem bảng nằm ở đâu.
Và hãy luôn dùng -v ON_ERROR_STOP=1 khi nạp tệp. Không có nó, một lỗi ở dòng 20 vẫn để psql chạy tiếp tới dòng 900 và báo "xong" một cách rất thuyết phục.
✍️ Bài tập¶
-
Giải thích bằng lời của bạn: vì sao PostgreSQL cần một con số cổng, trong khi Word thì không cần?
-
Cho lệnh sau. Hãy chỉ ra từng tham số trả lời cho câu hỏi nào trong ba câu "ở đâu — là ai — vào đâu":
-
Bạn gõ
SELECT count(*) FROM giao_vien;và nhậnERROR: relation "giao_vien" does not exist. Hãy nêu hai nguyên nhân có thể, và với mỗi nguyên nhân, một câu lệnh để xác nhận đúng là nó. -
Trong các dòng sau, dòng nào là lệnh meta của
psql, dòng nào là câu SQL? Dựa vào dấu hiệu gì mà bạn biết?\dt·SELECT 1;·\c truong_hoc·DROP TABLE lop;·\q -
Bạn của bạn nạp dataset xong,
\dthiện đủ 10 bảng, nhưngSELECT count(*) FROM diem;trả về312thay vì480. Chuyện gì nhiều khả năng đã xảy ra, và cách sửa an toàn nhất là gì?
Đáp án
Câu 1.
Word là một ứng dụng chạy ngay trên máy bạn: bạn mở tệp, sửa, đóng. Không ai từ máy khác cần "gõ cửa" Word của bạn cả.
PostgreSQL là một máy chủ: nó chạy ngầm liên tục và chờ nhiều máy khách kết nối tới — có thể từ chính máy bạn, có thể từ máy khác trong mạng. Mà một máy tính thường chạy nhiều máy chủ cùng lúc: máy chủ web, máy chủ mail, máy chủ database…
Cổng là con số để hệ điều hành biết gói tin gửi tới nên giao cho máy chủ nào. Giống như địa chỉ toà nhà (địa chỉ IP) là chưa đủ, còn cần số phòng (cổng) mới tới đúng người.
Câu 2.
| Tham số | Trả lời câu hỏi | Cụ thể |
|---|---|---|
-h localhost |
Ở đâu | Máy chủ nằm trên chính máy này |
-p 5433 |
Ở đâu | Cổng 5433 — không phải mặc định, chắc là do đã đổi cổng vì 5432 bị chiếm |
-U postgres |
Là ai | Đăng nhập bằng vai trò postgres |
-d truong_hoc |
Vào đâu | Vào database truong_hoc |
Thiếu mật khẩu trong lệnh là bình thường: psql sẽ hỏi riêng, hoặc lấy từ biến môi trường PGPASSWORD. Ghi mật khẩu thẳng vào dòng lệnh là thói quen xấu vì nó bị lưu vào lịch sử shell.
Câu 3.
Nguyên nhân 1 — đang đứng sai database. Bạn ở trong postgres chứ không phải truong_hoc.
Xác nhận:
Nếu trả về postgres thì đúng là nó. Sửa bằng \c truong_hoc.
Nguyên nhân 2 — dataset chưa được nạp (hoặc nạp dở). Đúng database rồi nhưng bảng chưa tồn tại.
Xác nhận bằng lệnh meta \dt: nếu hiện Did not find any relations. thì database rỗng. Sửa bằng cách chạy lại Bước 5.
(Một nguyên nhân thứ ba ít gặp hơn: gõ sai tên bảng — ví dụ giao_vien thành giaovien. \dt cũng giúp phát hiện ngay.)
Câu 4.
| Dòng | Loại | Dấu hiệu |
|---|---|---|
\dt |
Lệnh meta | Bắt đầu bằng \, không có ; |
SELECT 1; |
SQL | Kết thúc bằng ; |
\c truong_hoc |
Lệnh meta | Bắt đầu bằng \ |
DROP TABLE lop; |
SQL | Kết thúc bằng ; |
\q |
Lệnh meta | Bắt đầu bằng \ |
Quy tắc nhận biết: \ là của psql, ; là của máy chủ. Lệnh meta được psql xử lý tại chỗ và máy chủ không bao giờ nhìn thấy chúng — đó cũng là lý do bạn không dùng được \dt trong một ứng dụng web hay một công cụ khác.
Câu 5.
Nhiều khả năng tệp nạp bị dừng giữa chừng mà bạn ấy không để ý: một câu INSERT nào đó lỗi, nhưng vì thiếu -v ON_ERROR_STOP=1 nên psql vẫn chạy tiếp và kết thúc êm ru. Các bảng đã được tạo (nên \dt hiện đủ 10) nhưng dữ liệu chỉ vào được một phần.
Một khả năng khác: tệp đã bị nạp lồng vào một lần nạp trước đó bị lỗi, hoặc bị ngắt do mất kết nối giữa chừng.
Cách sửa an toàn nhất là nạp lại từ đầu, có bật cờ dừng khi lỗi:
Nạp lại hoàn toàn an toàn vì tệp mở đầu bằng một loạt DROP TABLE IF EXISTS ... CASCADE; — nó tự dọn sạch trước khi dựng lại. Lần này, nếu có lỗi thật, psql sẽ dừng ngay và in ra đúng dòng gây lỗi.
Sau đó chạy lại câu kiểm tra mười bảng ở Bước 6 để đối chiếu đủ mười con số.
🔑 Tóm tắt¶
- PostgreSQL là một máy chủ chạy ngầm liên tục, không phải ứng dụng bật/tắt;
psqlchỉ là một máy khách gõ cửa nó. - Mỗi lần kết nối phải nói đủ ba thứ — ở đâu (
-h,-p, mặc định cổng 5432), là ai (-U+ mật khẩu của vai trò PostgreSQL, không phải mật khẩu máy tính), vào đâu (-d truong_hoc). - Trong
psql, câu SQL kết thúc bằng;và đi tới máy chủ; lệnh meta bắt đầu bằng\và dopsqltự xử lý —\l,\dt,\d ten_bang,\c,\q. - Nạp dataset bằng
psql ... -v ON_ERROR_STOP=1 -f dataset/02-chuan-hoa.sql; cờON_ERROR_STOPlà thứ ngăn bạn nhận một database nạp dở mà không hay biết. - Mốc kiểm tra bắt buộc trước khi sang Bài 6:
\dthiện đủ 10 bảng vàSELECT count(*) FROM hoc_sinh;trả về đúng 40.