Chào các bạn, những guru PostgreSQL tương lai! Chủ đề hôm nay dành cho một trong những kỹ năng quý giá nhất trong lập trình — tránh lỗi. Tất nhiên là không thể tránh hết mọi lỗi, nhất là khi bạn mới bắt đầu học SQL. Nhưng hiểu nhanh về những lỗi thường gặp thì hoàn toàn có thể. Nó giống như đi trong phòng tối với nhiều góc cạnh: va đầu vài lần, nhưng sau đó bạn sẽ biết mọi thứ ở đâu. Và mình sẽ giúp bạn né mấy "góc nhọn" khi tạo và thay đổi bảng nhé.
Lỗi 1: Chọn sai kiểu dữ liệu
Làm việc với kiểu dữ liệu giống như chọn chìa khóa cho ổ khóa. "Chìa khóa" sai, tức là kiểu dữ liệu không phù hợp, có thể khiến bảng hoạt động không đúng hoặc kém hiệu quả.
Ví dụ lỗi:
Bạn muốn tạo một cột để lưu số điện thoại và theo thói quen chọn kiểu INTEGER. Nghe hợp lý vì số điện thoại là số mà. Nhưng vấn đề là INTEGER không phù hợp cho dữ liệu mà:
- Bắt đầu bằng số 0 (
0123456789sẽ thành123456789). - Có ký tự như "+" hoặc dấu cách.
-- Sai:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
phone_number INTEGER -- Ôi ôi
);
-- Đúng:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
phone_number VARCHAR(15) -- Phù hợp để lưu mọi định dạng số
);
Làm sao tránh?
Hãy phân tích kỹ bản chất dữ liệu bạn sẽ lưu trước khi chọn kiểu dữ liệu. Nếu không chắc, hãy xem tài liệu chính thức của PostgreSQL về kiểu dữ liệu.
Lỗi 2: Bỏ qua các ràng buộc NOT NULL, CHECK, UNIQUE
Ràng buộc giúp giữ cho dữ liệu nhất quán. Nếu quên chúng — bảng của bạn sẽ loạn lên với những giá trị rỗng ở nơi không nên có.
Ví dụ lỗi: Bạn tạo bảng lưu sinh viên, nhưng quên rằng tên và tuổi là bắt buộc.
-- Sai:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INTEGER
);
INSERT INTO students (name, age) VALUES (NULL, NULL); -- Ôi, cái gì đây?!
Cách đúng:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- Tên là bắt buộc
age INTEGER CHECK (age > 0) -- Tuổi phải lớn hơn 0
);
Làm sao tránh?
Luôn đặt ràng buộc cho các trường bắt buộc. Đây là kiểu "cơ chế bảo vệ" giúp ngăn dữ liệu lỗi lọt vào.
Lỗi 3: Vấn đề về tính duy nhất
Đôi khi bạn quên thêm ràng buộc UNIQUE cho cột cần giá trị duy nhất. Điều này dẫn đến dữ liệu bị trùng lặp.
Ví dụ lỗi: Bạn tạo bảng lưu email, nhưng quên thêm UNIQUE.
-- Sai:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100)
);
INSERT INTO users (email) VALUES ('user@example.com');
INSERT INTO users (email) VALUES ('user@example.com'); -- Email này đã có rồi!
Cách đúng:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100) UNIQUE -- Email duy nhất
);
Làm sao tránh?
Luôn thêm UNIQUE nếu giá trị cần duy nhất. Nếu muốn linh hoạt hơn, bạn có thể dùng CONSTRAINT với tên để xác định ràng buộc:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(100),
CONSTRAINT unique_email UNIQUE (email)
);
Lỗi 4: Lỗi khi thay đổi bảng (ALTER TABLE)
Dùng ALTER TABLE có thể khá "khó chịu", nhất là khi bảng đã có dữ liệu. Ví dụ, bạn có thể quên kiểm tra giá trị hợp lệ trong cột, dẫn đến lỗi khi thao tác với dữ liệu hiện có.
Ví dụ lỗi: Bạn muốn thêm ràng buộc NOT NULL cho cột đã có, nhưng trong cột đó lại có giá trị NULL.
-- Sai:
ALTER TABLE students ALTER COLUMN name SET NOT NULL; -- Lỗi!
Nếu bảng đã có dòng với NULL, PostgreSQL sẽ không cho bạn thêm ràng buộc này.
Làm sao?
Trước khi thêm ràng buộc, hãy chắc chắn dữ liệu đã hợp lệ. Ví dụ:
UPDATE students SET name = 'Khong biet' WHERE name IS NULL;
ALTER TABLE students ALTER COLUMN name SET NOT NULL;
Lỗi 5: Xóa bảng hoặc dữ liệu mà không kiểm tra
Xóa bảng bằng DROP TABLE hoặc dữ liệu bằng DELETE — là thao tác không thể hoàn tác. Vì vậy, trước khi xóa, hãy kiểm tra kỹ bạn đang xóa cái gì.
Ví dụ lỗi:
DROP TABLE courses; -- Ôi, không phải bảng này!
Làm sao tránh?
Dùng lệnh \dt trong psql để xem các bảng hiện có, và chắc chắn bạn xóa đúng bảng.
Hoặc dùng DROP TABLE IF EXISTS để tránh lỗi khi xóa bảng không tồn tại:
DROP TABLE IF EXISTS courses;
Lỗi 6: Vấn đề với bảng tạm thời
Bảng tạm thời sẽ biến mất khi kết thúc session. Nếu bạn lỡ dùng bảng tạm mà session đã kết thúc, sẽ bị lỗi.
Ví dụ lỗi:
CREATE TEMP TABLE temp_students (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
-- Đã kết thúc session, giờ thì...
SELECT * FROM temp_students; -- Lỗi: bảng không còn nữa!
Làm sao tránh?
Lưu dữ liệu tạm cần dùng giữa các session vào bảng thường, hoặc ghi chú rõ việc sử dụng trong cùng một session.
Lỗi 7: Quên ràng buộc khi test
Thường khi phát triển, bạn có thể bỏ qua một số ràng buộc, nghĩ rằng "để sau thêm". Nhưng thực tế, "để sau" dễ bị quên lắm.
Ví dụ lỗi:
CREATE TABLE test_table (
id SERIAL PRIMARY KEY,
name VARCHAR(50)
);
-- Thêm dữ liệu:
INSERT INTO test_table (name) VALUES ('Ten trung lap');
INSERT INTO test_table (name) VALUES ('Ten trung lap'); -- Bắt đầu có vấn đề...
Làm sao tránh?
Tạo bảng với ràng buộc ngay từ lúc test luôn cho khỏe:
CREATE TABLE test_table (
id SERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE -- Đỡ đau đầu về sau
);
GO TO FULL VERSION