Tôi muốn có thể dự đoán liệu XÓA có bị vi phạm ràng buộc hay không mà không thực sự xóa.
Lựa chọn của tôi để làm điều này là gì? Có cách nào đơn giản để thực hiện "chạy khô" XÓA không?
Tôi muốn có thể dự đoán liệu XÓA có bị vi phạm ràng buộc hay không mà không thực sự xóa.
Lựa chọn của tôi để làm điều này là gì? Có cách nào đơn giản để thực hiện "chạy khô" XÓA không?
Câu trả lời:
Nếu mục tiêu của bạn là xử lý tất cả các lần xóa chỉ khi tất cả chúng thành công, tại sao không sử dụng TRY / CATCH:
BEGIN TRANSACTION;
BEGIN TRY
DELETE #1;
DELETE #2;
DELETE #3;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH
Nếu mục tiêu là cho phép tất cả các lần xóa thành công thành công ngay cả khi một hoặc nhiều lần sẽ thất bại, thì bạn có thể sử dụng TRY / CATCH riêng lẻ, ví dụ:
BEGIN TRY
DELETE #1;
END TRY
BEGIN CATCH
PRINT 1;
END CATCH
BEGIN TRY
DELETE #2;
END TRY
BEGIN CATCH
PRINT 1;
END CATCH
Một tùy chọn là bắt đầu một giao dịch, chạy xóa của bạn và sau đó luôn quay lại:
begin tran
delete Table1 where col1 = 1
-- Test whether it is there
select * from Table1 where col1 = 1
rollback tran
-- Confirm that it is still there
select * from Table1 where col1 = 1
Tôi muốn cải thiện giải pháp do Aaron Bertrand cung cấp với một số mã, trong trường hợp bạn muốn thử thêm bất kỳ phần tử nào của bảng, quản lý các ngoại lệ để bỏ qua thất bại hoặc cũng dừng các lỗi xử lý sau.
Cái này sẽ chọn các bản ghi từ bảng và sau đó cố gắng xóa chúng mà không có ngoại lệ:
DECLARE @MaxErrors INT
SET @MaxErrors = 5; // Setting 0 will stop process after the first error!
SELECT
[Id]
, ROW_NUMBER() OVER (ORDER BY Id ASC) AS [Index]
INTO #DeletingItems
FROM myTable
DECLARE @Current INT, @Max INT, @Id INT, @TotErrors INT
SELECT
@Current = 1
, @TotErrors = 0
, @Max = MAX([Index])
FROM #DeletingTable
WHILE @Current <= @Max
BEGIN
SELECT
@Id = [Id]
FROM #DeletingItems
WHERE
[Index] = @Index;
BEGIN TRANSACTION;
BEGIN TRY
DELETE FROM myTable WHERE [Id] = @Id;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @TotErrors = @TotErrors + 1;
IF @TotErrors > @MaxErrors
BREAK;
END CATCH
SET @Current = @Current + 1;
END