Khi xóa một hàng có ID ở giữa, các ID sau đó bị "lõi" (gap). Để sắp xếp lại liên tục, dùng UPDATE giảm giá trị ID lớn hơn ID đã xóa.
Cú pháp
-- 1. Xóa hàng DELETE FROM tên_bảng WHERE id_cột = giá_trị_cần_xóa; -- 2. Cập nhật ID các hàng sau UPDATE tên_bảng SET id_cột = id_cột - 1 WHERE id_cột > giá_trị_cần_xóa;
Ví dụ minh họa
Tạo bảng (không AUTO_INCREMENT để demo dễ):
mysql> CREATE TABLE ReorderSortDemo (UserId INT);
Chèn dữ liệu không theo thứ tự:
mysql> INSERT INTO ReorderSortDemo VALUES (14), (4), (6), (3), (8), (18), (1), (11), (16);
Xem dữ liệu (9 hàng):
mysql> SELECT * FROM ReorderSortDemo;
+--------+ | UserId | +--------+ | 14 | | 4 | | 6 | | 3 | | 8 | | 18 | | 1 | | 11 | | 16 | +--------+
Xóa hàng UserId = 8:
mysql> DELETE FROM ReorderSortDemo WHERE UserId = 8; Query OK, 1 row affected (0.20 sec)
Kết quả sau xóa (8 hàng, thiếu 8):
mysql> SELECT * FROM ReorderSortDemo;
+--------+ | UserId | +--------+ | 14 | | 4 | | 6 | | 3 | | 18 | | 1 | | 11 | | 16 | +--------+
Sắp xếp lại: giảm 1 cho tất cả UserId > 8:
mysql> UPDATE ReorderSortDemo
-> SET UserId = UserId - 1
-> WHERE UserId > 8;
Query OK, 4 rows affected (0.22 sec)
Rows matched: 4 Changed: 4 Warnings: 0
Kết quả cuối (UserId 11→10, 14→13, 16→15, 18→17):
mysql> SELECT * FROM ReorderSortDemo;
+--------+ | UserId | +--------+ | 13 | | 4 | | 6 | | 3 | | 17 | | 1 | | 10 | | 15 | +--------+
⚠️ Cảnh báo quan trọng
- KHÔNG làm điều này trên cột PRIMARY KEY / AUTO_INCREMENT đang được tham chiếu bởi FOREIGN KEY từ bảng khác → sẽ vi phạm ràng buộc tham chiếu
- ID là định danh ổn định, không nên thay đổi sau khi đã tạo
- Gap trong AUTO_INCREMENT là bình thường, không ảnh hưởng hiệu năng
Khi nào cần renumber?
- Cột thứ tự hiển thị (display_order, sort_order) — không phải khóa chính
- Dữ liệu tạm, staging table trước khi import
- Demo/giáo dục
Thay vào đó: Dùng cột riêng sort_order INT cho thứ tự hiển thị, giữ ID bất biến.