มีวิธีทดสอบว่า DELETE จะล้มเหลวเนื่องจากข้อ จำกัด หรือไม่


10

ฉันต้องการที่จะคาดการณ์ว่าจะมีการลบ DELETE หรือไม่โดยไม่ทำการลบ

ตัวเลือกของฉันสำหรับการทำสิ่งนี้มีอะไรบ้าง มีวิธีง่ายๆในการทำ "dry run" ของ DELETE หรือไม่?


คุณกำลังพยายามป้องกันข้อยกเว้นสำหรับข้อความนี้เพียงอย่างเดียวหรือคุณพยายามบรรเทาข้อผิดพลาดในชุดข้อมูลขนาดใหญ่ที่มีการลบนี้หรือไม่?
Aaron Bertrand

3
คุณสามารถตรวจสอบเพื่อดูว่ามี FK อยู่หรือไม่และเรียกใช้คำสั่ง SELECT เพื่อตรวจสอบค่าหรือไม่
SQLRockstar

แอรอน: เราจำเป็นต้องเรียกใช้ชุดของ DELETE หลายรายการในการทำธุรกรรมแยกต่างหาก หากล้มเหลวอื่น ๆ มีความมุ่งมั่นแล้ว (การออกแบบที่ไม่ดีตั้งแต่เริ่มต้นฉันรู้ แต่ไม่ใช่แอปพลิเคชันของฉันและไม่เปลี่ยนแปลง) วิธีแก้ปัญหาที่ดีที่สุดในขณะนี้ดูเหมือนจะเป็นการตรวจสอบแบบแห้งเพื่อดูว่า DELETE จะล้มเหลวหรือไม่
Jay Sullivan

ยังไม่แน่ใจว่าฉันเข้าใจ คุณกำลังพยายามให้ส่วนที่เหลือของการลบประสบความสำเร็จหรือคุณพยายามตรวจสอบล่วงหน้าว่าการลบทั้งหมดจะประสบความสำเร็จหรือไม่ควรมีอย่างใดอย่างหนึ่งหรือไม่
Aaron Bertrand

แอรอน: ขอโทษที่ฉันไม่ได้อธิบายให้ชัดเจน แต่ใช่ฉันพยายามทำให้แน่ใจว่าทุกคนประสบความสำเร็จหรือไม่สำเร็จเลย
Jay Sullivan

คำตอบ:


24

หากเป้าหมายของคุณคือการดำเนินการลบทั้งหมดหากพวกเขาทั้งหมดประสบความสำเร็จทำไมไม่ใช้ TRY / CATCH:

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

หากเป้าหมายคือการอนุญาตให้ลบที่ประสบความสำเร็จทั้งหมดประสบความสำเร็จแม้ว่าจะมีอย่างน้อยหนึ่งรายการจะล้มเหลวคุณสามารถใช้ TRY / CATCH แต่ละรายการเช่น

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

ทางเลือกหนึ่งคือเริ่มต้นธุรกรรมเรียกใช้การลบของคุณจากนั้นย้อนกลับทุกครั้ง:

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
และถ้าการลบสำเร็จให้รันอีกครั้งหรือไม่ เกิดอะไรขึ้นถ้าการลบมีราคาแพงมาก และถ้าการลบล้มเหลวจะเกิดอะไรขึ้น คุณลบแล้วหนึ่งรายการและเลือกสองรายการ ฉันจะตัดสินใจย้ายในการลบครั้งถัดไปได้อย่างไร
Aaron Bertrand

1
หากสิ่งเหล่านั้นเป็นส่วนหนึ่งของข้อกำหนดเหล่านั้นก็ควรได้รับการจัดการ คำตอบนี้เกี่ยวข้องกับ "แบบง่าย" แบบแห้ง "
GaTechThomas

พวกเขาไม่ได้เมื่อคุณส่งคำตอบของคุณเป็นครั้งแรก แต่พวกเขาได้รับการชี้แจงในขณะนี้
Aaron Bertrand

4
@GaTechThomas Aaron มีส่วนช่วยอย่างมากดังนั้นบางครั้งเขาก็สรุป แต่ฉันมั่นใจว่าความตั้งใจของเขาคือไม่ก้าวร้าว ฉันพูดถึงเรื่องนี้ในThe Heapและฉันก็รู้สึกซาบซึ้งใจที่มีโอกาสได้ร่วมงานกับคุณเช่นกัน
แจ็คบอกว่าลอง topanswers.xyz

1
@ JackDouglas ฉันได้อ่านความคิดเห็นของฮีปที่คุณอ้างอิงและเข้าใจประเด็นแล้ว ความคิดเห็นของชุมชนนั้นสมเหตุสมผลยกเว้นส่วนที่ฉันถูกเรียกตัวตลกเพื่อชี้ให้เห็นความก้าวร้าวของเขา ฉันไม่เข้าใจว่าฉันเป็นคนก้าวร้าวอย่างไร ฉันโพสต์คำตอบที่ถูกต้องสำหรับคำถามตามที่โพสต์ไว้ในขณะนั้น มันไม่ได้ขอคุณภาพการผลิต - บางครั้งคุณต้องการได้อย่างรวดเร็วและง่ายดาย ดังนั้นในคำตอบของฉันฉันได้รับคำถามแหลม ลักษณะที่ปรากฏคือเขาปฏิเสธคำตอบของฉันเพื่อที่เขาจะได้เลือก เราควรเอากระทู้นี้ไปที่อื่นไหม?
GaTechThomas

0

ฉันต้องการปรับปรุงวิธีแก้ปัญหาที่มีให้โดย Aaron Bertrand ด้วยรหัสบางส่วนในกรณีที่คุณต้องการเพิ่มองค์ประกอบของตารางใด ๆ จัดการข้อยกเว้นเพื่อเพิกเฉยต่อความล้มเหลวหรือหยุดกระบวนการหลังข้อผิดพลาด

อันนี้จะเลือกบันทึกจากตารางแล้วพยายามลบโดยไม่มีข้อยกเว้น:

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
ทำไม? นี่เป็นการปรับปรุงคำตอบที่ยอมรับได้อย่างไร
ToolmakerSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.