Sắp xếp các xóa theo tầng thích hợp là điều khôn ngoan và thường là giải pháp chính xác cho vấn đề này. Đối với một số trường hợp đặc biệt, có một giải pháp khác có thể phù hợp.
Nếu bạn cần thực hiện nhiều lần xóa dựa trên một tập hợp dữ liệu chung, bạn có thể sử dụng Biểu thức bảng chung (CTE) .
Thật khó để đưa ra một ví dụ đơn giản vì trường hợp sử dụng chính cho việc này có thể bị che phủ bởi việc xóa theo tầng.
Đối với ví dụ, chúng tôi sẽ xóa tất cả các mục trong bảng A có giá trị nằm trong tập hợp các giá trị mà chúng tôi đang xóa khỏi bảng B. Thông thường đây sẽ là các khóa, nhưng nếu chúng không có, thì không thể sử dụng xóa theo tầng .
Để giải quyết vấn đề này, bạn sử dụng CTE
WITH Bdeletes AS (
DELETE from B where IsSomethingToDelete = true returning ValueThatRelatesToA
)
delete from A where RelatedValue in (select ValueThatRelatesToA from Bdeletes)
Ví dụ này cố tình đơn giản vì quan điểm của tôi không phải là tranh luận về ánh xạ khóa, v.v. mà là chỉ ra cách hai hoặc nhiều lần xóa có thể được thực hiện trên một tập dữ liệu được chia sẻ. Điều này cũng có thể phức tạp hơn nhiều, bao gồm các lệnh cập nhật, v.v.
Đây là một ví dụ phức tạp hơn (từ cơ sở dữ liệu cá nhân của Darth Vader). Trong trường hợp này, chúng ta có một bảng tham chiếu đến một bảng địa chỉ. Chúng ta cần xóa các địa chỉ khỏi bảng địa chỉ nếu chúng nằm trong danh sách các hành tinh mà anh ta đã phá hủy. Chúng tôi muốn sử dụng thông tin này để xóa khỏi bảng mọi người, nhưng chỉ khi họ ở trên hành tinh (hoặc trong danh sách tiêu diệt chiến tích của anh ấy)
with AddressesToDelete as (
select AddressId from Addresses a
join PlanetsDestroyed pd on pd.PlanetName = a.PlanetName
),
PeopleDeleted as (
delete from People
where AddressId in (select * from AddressesToDelete)
and OffPlanet = false
and TrophyKill = false
returning Id
),
PeopleMissed as (
update People
set AddressId=null, dead=(OffPlanet=false)
where AddressId in (select * from AddressesToDelete)
returning id
)
Delete from Addresses where AddressId in (select * from AddressesToDelete)
Bây giờ cơ sở dữ liệu của anh ấy đã được cập nhật. Không có lỗi toàn vẹn do xóa Địa chỉ. Lưu ý rằng trong khi chúng tôi trả lại dữ liệu từ bản cập nhật và lần xóa đầu tiên, điều đó không có nghĩa là chúng tôi phải sử dụng nó. Tôi không chắc liệu bạn có thể đặt lệnh xóa trong CTE mà không có dữ liệu trả về hay không (SQL của tôi cũng có thể sai khi sử dụng tính năng trả về từ bản cập nhật - Tôi không thể chạy thử thao tác này vì Darth V. đã ở trong một tâm trạng cáu kỉnh.