Dưới đây là một số tùy chọn để xóa các hàng trùng lặp khỏi bảng trong Cơ sở dữ liệu Oracle khi các hàng đó có khóa chính hoặc cột định danh duy nhất.
Trong những trường hợp như vậy, khóa chính phải được bỏ qua khi so sánh các hàng trùng lặp (do thực tế là khóa chính giữ các giá trị duy nhất).
Dữ liệu Mẫu
Các ví dụ của chúng tôi sử dụng dữ liệu sau:
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
2 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
6 | Wag | Johnson |
7 | Wag | Johnson |
Chúng ta có thể thấy rằng hai hàng đầu tiên là trùng lặp, ba hàng cuối cùng cũng vậy.
DogId
cột chứa các giá trị duy nhất (vì đó là khóa chính của bảng), nhưng chúng tôi đang bỏ qua cột đó khi so sánh các bản sao. Bạn có thể thường thấy mình cần loại bỏ các bảng có chứa khóa chính và vì vậy, các ví dụ sau đây có thể được sử dụng để làm điều đó.
Tùy chọn 1
Đây là tùy chọn đầu tiên của chúng tôi để loại bỏ lừa đảo trong bảng trên:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
MINUS SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Các bản sao đã bị xóa (nhưng một hàng của mỗi bản sao vẫn còn).
Ngoài ra, chúng ta có thể sử dụng MAX ()
thay vì MIN ()
chức năng thay đổi các hàng bị xóa.
Tùy chọn 2
Trong ví dụ này (và các ví dụ sau), chúng tôi sẽ giả định rằng bảng đã được khôi phục về trạng thái ban đầu (với các bản sao).
Đây là một ví dụ khác giúp loại bỏ bảng và sau đó chọn các hàng còn lại:
DELETE FROM Dogs WHERE DogId IN (
SELECT d2.DogId
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId=(
SELECT MAX(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
)
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
2 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
7 | Wag | Johnson |
Lưu ý rằng tôi đã sử dụng MAX ()
hàm thay vì MIN ()
mà tôi đã sử dụng trong ví dụ trước. Chúng ta có thể thấy ảnh hưởng của điều này đối với hoạt động khử lừa đảo. Nó đã xóa các hàng khác nhau khỏi bảng.
Tùy chọn 3
Đây là một tùy chọn không yêu cầu sử dụng MIN ()
hoặc MAX ()
:
DELETE FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.DogId > d2.DogId
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Tùy chọn 4
Đây là một tùy chọn khác:
DELETE FROM Dogs
WHERE DogId > (
SELECT MIN(DogId) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Tùy chọn 5
Mỗi hàng trong Oracle có một rowid
cột giả trả về địa chỉ của hàng. rowid
là mã định danh duy nhất cho các hàng trong bảng và thường giá trị của nó xác định duy nhất một hàng trong cơ sở dữ liệu (mặc dù điều quan trọng cần lưu ý là các hàng trong các bảng khác nhau được lưu trữ cùng nhau trong cùng một cụm có thể có cùng một rowid ).
Do đó, chúng tôi có thể sử dụng rowid
trong truy vấn của chúng tôi thay vì DogId
cột:
DELETE FROM Dogs
WHERE EXISTS (
SELECT 1 FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
AND Dogs.rowid > d2.rowid
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |
Mặc dù ví dụ này có vẻ hơi thừa, vì chúng ta đã có cột khóa chính, có thể có những trường hợp bạn thích sử dụng rowid
. rowid
có thể hữu ích nếu bạn không thể sử dụng cột khóa chính vì lý do nào đó hoặc nếu bảng không có khóa chính. Ngoài ra, tài liệu của Oracle đề cập rằng rowid
giá trị là cách nhanh nhất để truy cập vào một hàng.
Tùy chọn 6
Và đây là ví dụ khác, nhưng với rowid
thay vì khóa chính:
DELETE FROM Dogs
WHERE rowid > (
SELECT MIN(rowid) FROM Dogs d2
WHERE Dogs.FirstName = d2.FirstName
AND Dogs.LastName = d2.LastName
);
SELECT * FROM Dogs;
Kết quả:
DOGID | FIRSTNAME | LASTNAME |
---|---|---|
1 | Vỏ cây | Smith |
3 | Gâu | Jones |
4 | Ruff | Robinson |
5 | Wag | Johnson |