Kısıtlamalar nedeniyle DELETE'in başarısız olup olmadığını test etmenin bir yolu var mı?


10

Silmeyi gerçekleştirmeden bir DELETE değerinin bir kısıtlama ihlaline girip girmeyeceğini tahmin edebilmek istiyorum.

Bunu yapmak için seçeneklerim nelerdir? SİLME "kuru çalışma" yapmanın basit bir yolu var mı?


Yalnızca bu ifade için özel durumu önlemeye mi çalışıyorsunuz, yoksa bu silme işlemini içeren daha büyük bir grupta hata işlemeyi kolaylaştırmaya mı çalışıyorsunuz?
Aaron Bertrand

3
Bir FK'nin var olup olmadığını kontrol edebilir ve değerleri kontrol etmek için bir SELECT ifadesi çalıştırabilir misiniz?
SQLRockstar

Aaron: Ayrı işlemlerde birkaç DELETE grubunu çalıştırmamız gerekiyor. Biri başarısız olursa, diğerleri zaten kararlıdır. (Baştan beri kötü tasarım, biliyorum, ama bu benim uygulamam değil ve değişmiyor.) Şu anda en iyi çözüm, DELETE'lerin başarısız olup olmayacağını görmek için kuru bir kontrol yapmak gibi geliyor.
Jay Sullivan

Hala anladığımdan emin değilim. Diğer silme işlemlerinin başarılı olmasına izin vermeye mi çalışıyorsunuz, yoksa tüm silme işlemlerinin başarılı olup olmayacağını mı kontrol ediyorsunuz?
Aaron Bertrand

Aaron: Üzgünüm, netleştirmedim, ama evet, hepsinin başarılı olduğundan ya da hiçbirinin başarılı olmadığından emin olmaya çalışıyorum.
Jay Sullivan

Yanıtlar:


24

Hedefiniz tüm silme işlemlerini yalnızca hepsi başarılı olursa işlemekse, neden sadece TRY / CATCH kullanmıyorsunuz:

BEGIN TRANSACTION;
BEGIN TRY
  DELETE #1;
  DELETE #2;
  DELETE #3;
  COMMIT TRANSACTION;
END TRY
BEGIN CATCH
  ROLLBACK TRANSACTION;
END CATCH

Hedef, bir veya daha fazla başarısız olsa bile tüm başarılı silme işlemlerinin başarılı olmasına izin vermekse, ayrı ayrı TRY / CATCH kullanabilirsiniz;

BEGIN TRY
  DELETE #1;
END TRY
BEGIN CATCH
  PRINT 1;
END CATCH

BEGIN TRY
  DELETE #2;
END TRY
BEGIN CATCH
  PRINT 1;
END CATCH

6

Seçeneklerden biri, bir işleme başlamak, silmenizi çalıştırmak ve ardından her zaman geri almaktır:

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

1
Silme işlemi başarılı olursa, tekrar çalıştırılsın mı? Silme işlemi çok pahalıysa ne olur? Silme işlemi başarısız olursa, ne olacak? Bir silme ve iki seçim yaptınız. Bir sonraki silme işlemine geçip geçmemeye nasıl karar verebilirim?
Aaron Bertrand

1
Bunlar gereksinimlerin bir parçasıysa, ele alınmalıdır. Bu cevap "basit" kuru çalışma "ile ilgilidir.
GaTechThomas

Cevabınızı ilk gönderdiğinizde değildi, ama şimdi açıklığa kavuştular.
Aaron Bertrand

4
@GaTechThomas Aaron çok katkıda bulunuyor, bu yüzden bazen kısa, ama niyetinin agresif olmaması gerektiğinden eminim. Bunu Öbek'te tartıştım ve sizinle de bunu yapma şansı için minnettar olurum.
Jack diyor ki topanswers.xyz

1
@JackDouglas Başvuru yaptığınız ve anladığınız Heap yorumlarını okudum. Topluluk yorumları, saldırganlığına işaret ettiğim için palyaço olarak adlandırılan bölüm dışında mantıklıydı. Saldırgan olarak görülen kişinin nasıl olduğumu anlamıyorum. O zaman sorulduğu gibi soruya meşru bir cevap gönderdim. Üretim kalitesi istemedi - bazen sadece hızlı ve kolay ihtiyacınız var. Öyleyse benim cevap ben sivri sorular olsun. Görünüşe göre, cevabımı alması için cevabımı kötüleştiriyordu. Bu konuyu başka bir yere mi götürmeliyiz?
GaTechThomas

0

Bir tablodaki herhangi bir öğeyi eklemek, başarısızlıkları yoksaymak için özel durumları yönetmek veya ayrıca işlem sonrası hataları durdurmak için bazı kodlarla Aaron Bertrand tarafından sağlanan çözümü geliştirmek istiyorum.

Bu kayıtlar tablodan seçilir ve istisnasız olarak silinmeye çalışır:

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

1
Neden? Bu, kabul edilen cevaba göre nasıl bir gelişme?
ToolmakerSteve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.