Hôm nay tụi mình sẽ đến với một viên gạch quan trọng nữa trong kho kiến thức mới của bạn — cập nhật dữ liệu. Xem thử trong PostgreSQL làm sao để thay đổi thông tin đã có bằng lệnh UPDATE. Tại sao lại quan trọng? Vì ngoài đời dữ liệu không đứng yên đâu. Ví dụ bạn của bạn đổi số điện thoại, hay sinh viên chuyển sang nhóm khác — tất nhiên bạn sẽ muốn update lại trong database rồi.
Khi crush hồi cấp ba của bạn, Svetka Sokolova, bỗng thành Svetka Khachaturyan (vì đời mà), thì cũng phải sửa lại trong database thôi. Những tình huống cần update dữ liệu thì gặp hoài luôn:
- Sửa lỗi trong bản ghi.
- Cập nhật thông tin (chuyển nhà, đổi trạng thái).
- Thay đổi hàng loạt, ví dụ tăng lương cho nhân viên.
Cập nhật dữ liệu là cách để đổi giá trị của một hoặc nhiều cột cho một hoặc nhiều dòng trong bảng, mà không cần thêm bản ghi mới.
Cú pháp lệnh UPDATE
Lệnh UPDATE trong PostgreSQL có cú pháp khá dễ hiểu. Xem cấu trúc nè:
UPDATE bảng
SET column1 = value1,
column2 = value2
WHERE điều_kiện;
Giải thích:
bảng: tên bảng mà bạn muốn thay đổi gì đó.SET column = value: tham số xác định cột nào cần đổi và giá trị mới là gì.WHERE điều_kiện: điều kiện chỉ định dòng nào cần update (rất quan trọng để không update hết tất cả).
Điểm mấu chốt: nếu bạn quên thêm WHERE (hoặc viết sai), thay đổi của bạn sẽ áp dụng cho tất cả các dòng trong bảng. Thế là toang luôn đó.
Ví dụ: đổi tên sinh viên
Giả sử bạn có bảng students với các cột id, name, email. Bạn muốn đổi tên sinh viên có id = 1 thành "Maria Chi".
UPDATE students
SET name = 'Maria Chi'
WHERE id = 1;
Lệnh này sẽ tìm dòng có id = 1 và update cột name thành giá trị mới. Dễ mà đúng không?
Cập nhật nhiều cột cùng lúc
Thường thì bạn sẽ muốn đổi nhiều giá trị trong một bản ghi. Ví dụ, sinh viên đổi không chỉ tên mà còn cả email. Làm như này nè:
UPDATE students
SET name = 'Otto Lin',
email = 'otto.lin@example.com'
WHERE id = 2;
Ở đây mình update cả name và email cho sinh viên có id = 2. PostgreSQL cho phép bạn ghi nhiều cặp cột=giá_trị cách nhau bằng dấu phẩy trong phần SET.
Cập nhật nhiều dòng
Làm sao nếu bạn muốn đổi dữ liệu cho nhiều dòng cùng lúc? Ví dụ, bạn muốn chuyển một nhóm sinh viên sang lớp mới. Có thể update các dòng thỏa mãn điều kiện nào đó. Giả sử có cột group_number, và bạn muốn chuyển tất cả sinh viên từ nhóm 101 sang nhóm 202:
UPDATE students
SET group_number = 202
WHERE group_number = 101;
Lệnh này sẽ update tất cả dòng mà group_number bằng 101, đổi thành 202.
5. Điều kiện WHERE: cẩn thận nha!
Như đã nói, WHERE là phao cứu sinh của bạn. Không có nó thì câu lệnh sẽ ảnh hưởng tới tất cả các dòng trong bảng. Ví dụ, lệnh sau sẽ update NHÓM của tất cả sinh viên, không chỉ nhóm 101. Đó là điều bạn chắc chắn không muốn đâu:
UPDATE students
SET group_number = 202;
Làm ơn, luôn luôn thêm WHERE nếu không muốn phá nát dữ liệu. Cẩn thận vẫn hơn.
Hãy nghĩ về lệnh UPDATE như lệnh đổi giá trị các cột trong bảng, chứ không phải dòng. Mục tiêu là gán giá trị mới cho tất cả ô của một cột nào đó. Và chỉ khi có WHERE thì mới không đổi hết mọi dòng.
Cập nhật dựa trên dữ liệu từ bảng khác
Đôi khi bạn không chỉ muốn "gõ" giá trị bằng tay, mà còn update giá trị trong bảng A dựa vào dữ liệu từ bảng B. Kiểu này gặp hoài — nhất là khi dữ liệu lưu riêng: ví dụ tính toán ở một bảng, còn profile user ở bảng khác.
Giả sử bạn có bảng students, cần update cột debt dựa vào bảng payments, nơi lưu số nợ hiện tại (due_amount). Mỗi bản ghi trong students sẽ có bản ghi tương ứng trong payments qua trường student_id.
Cú pháp sẽ như này:
UPDATE students
SET debt = payments.due_amount
FROM payments
WHERE students.id = payments.student_id;
Chuyện gì xảy ra:
- PostgreSQL dùng
FROM paymentslàm nguồn dữ liệu. - Điều kiện
WHEREnối các dòng giữa hai bảng. - Chỉ update những dòng
studentscó bản ghi tương ứng trongpayments.
Quan trọng: trong UPDATE ... FROM thực ra là có một cái JOIN ngầm — JOIN, chỉ là không ghi từ khóa JOIN thôi.
Thực chất bên trong là JOIN ngầm. Thực tế nó kiểu như này:
UPDATE students
SET debt = p.due_amount
FROM payments p
JOIN students s ON s.id = p.student_id
WHERE students.id = p.student_id;
Làm sao xem trước cái gì sẽ được update
Trước khi chạy UPDATE, rất nên xem thử cái gì sẽ bị đổi. Có thể dùng SELECT viết cùng nguyên tắc:
SELECT
students.id,
students.name,
students.debt AS old_debt,
payments.due_amount AS new_debt
FROM students
JOIN payments ON students.id = payments.student_id;
Kết quả sẽ cho thấy:
- giá trị nợ cũ (
old_debt); - giá trị mới sẽ lấy từ bảng
payments(new_debt).
Cách này giúp bạn kiểm tra logic trước khi ghi đè dữ liệu mãi mãi.
Những bẫy tiềm ẩn
- Nếu
paymentscó nhiều bản ghi cho một sinh viên,UPDATEsẽ báo lỗi:more than one row returned. Bạn phải dùng hàm tổng hợp (MAX,SUM,LIMIT 1), hoặc đảm bảostudent_idtrongpaymentslà duy nhất. - Đừng quên,
UPDATE ... FROMlà đặc sản của PostgreSQL, không chạy được kiểu này ở vài hệ quản trị khác (ví dụ MySQL).
Ví dụ thực tế
Ví dụ 1: Đổi trạng thái sinh viên
Giả sử sinh viên hoàn thành khóa học sẽ có trạng thái "tốt nghiệp". Có cột status. Để update trạng thái cho sinh viên có completed_course = true:
UPDATE students
SET status = 'tốt nghiệp'
WHERE completed_course = true;
Ví dụ 2: Tăng lương cho nhân viên
Nếu bạn có bảng employees, muốn tăng lương 10% cho tất cả ai làm ở phòng Sales:
UPDATE employees
SET salary = salary * 1.10
WHERE department = 'Sales';
Ở đây mình dùng phép toán ngay trong phần SET. Rất tiện cho thay đổi hàng loạt.
Ví dụ 3: Update có điều kiện
Đôi khi cần update dữ liệu tùy theo điều kiện. Ví dụ, nếu lương nhân viên dưới 50,000 thì tăng 20%, còn trên thì tăng 10%:
UPDATE employees
SET salary = CASE
WHEN salary < 50000 THEN salary * 1.20
ELSE salary * 1.10
END;
Lệnh này dùng cấu trúc CASE để đặt quy tắc update khác nhau tùy giá trị salary.
Lỗi thường gặp khi dùng UPDATE
Chắc bạn cũng đoán ra lỗi phổ biến nhất là gì rồi nhỉ? Đúng rồi, quên WHERE. Thử tưởng tượng: bạn có database 10,000 nhân viên, mà lỡ tăng lương cho tất cả. Nhân viên thì vui, nhưng sự nghiệp của bạn thì... hơi căng.
Một lỗi nữa là update nhầm cột. Luôn kiểm tra kỹ bạn đang ghi gì vào đâu. Một câu SELECT trước UPDATE có thể cứu bạn cả đống thời gian đó.
GO TO FULL VERSION