ما هي الطريقة المقبولة لحذف السجلات المشار إليها بواسطة جدول مفرق / الانضمام؟

StackOverflow https://stackoverflow.com/questions/1477689

  •  16-09-2019
  •  | 
  •  

سؤال

لدي ثلاث طاولات على النحو التالي، مع عدم وجود علاقات متتالية (لا أريد هذا، حيث يتم إدارة قاعدة البيانات بشكل أساسي بواسطة Nibernate).

Invoice
(
    entity_id int not null,
    ...
)

Ticket
(
    entity_id int not null,
    ...
)

InvoiceTicket
(
    InvoiceId --> Not-null foreign key to Invoice.entity_id
    TicketId --> Not-null Foreign key to Ticket.entity_id
)

ما أحاول القيام به هو حذف الفواتير والتذاكر وصفقات Invoiceticket ذات الصلة نظرا لمعايير التذاكر. ولكن علي القيام بذلك خارجيا إلى تطبيقنا، وبالتالي لماذا أقوم ببناء استعلام SQL للقيام بذلك.

لقد حذفت بالفعل جميع التبعيات إلى كل من الفاتورة والتذكرة، ولا مشكلة. منذ الفاتورة والتذكرة المشار إليها بواسطة Invoiceticket، يجب أن أحذف صفوف Invoiceticket أولا. ومع ذلك، إذا قمت بذلك، فسيتم كسر رابطي إلى جدول الفاتورة (لا يزال بإمكاني حذف تذاكر الفائدة، ولكن لم يعد الفواتير).

ما هي الطريقة المقبولة لأداء هذه العملية باستخدام SQL؟

قمت بحل المشكلة بالفعل باستخدام جدول مؤقت وملء صفوف الفائدة من جدول الفتاتيكيت، ولكن ما يفعله الآخرون لحل هذا النوع من المشكلة؟ أتصور أنك يمكن أن تفعل ذلك مع إجراء مخزن أيضا، لكنني لست على دراية بكتابة تلك. هل هناك طريقة مباشرة للقيام بهذه العملية من خلال استعلامات SQL؟

هل كانت مفيدة؟

المحلول

إذا كانت الفواتير موجودة بشكل صحيح بدون فواتير مرتبطة، فحول rbarryyoung هو حماقة. انها حذف كل هذه الفاتورة.

في هذه الحالة، من أجل بشكل صحيح حدد مجموعة الفواتير للحذف، يجب عليك أولا الاستعلام عنها وتعيينها جانبا.

نصائح أخرى

حسنا، إليك كيف سأفعل ذلك:

BEGIN TRANSACTION
    DELETE FROM InvoiceTicket
    WHERE EXISTS(
        SELECT *
        FROM TICKET t
        WHERE {t.* conditions are met}
        )

    DELETE FROM Ticket
    WHERE {t.* conditions are met}

    DELETE FROM Invoice
    WHERE NOT EXISTS(
        SELECT *
        FROM InvoiceTicket it
        WHERE Invoice.entity_id = InvoiceTicket.InvoiceId
        )
COMMIT TRANSACTION

وقد أشار بشكل صحيح إلى أن هذا النهج (أعلاه) يعمل فقط إذا كانت الفواتير تتطلب تذكرة واحدة مرتبطة واحدة على الأقل. في حين أن هذا صحيح، فإنه يرفع أيضا سؤال التحدث، الذي تريد حقا حذف كل فاتورة مرتبطة بتذاكر المطابقة الخاصة بك؟ لأنها قد ترتبط أيضا بالتذاكر الأخرى غير المحذوفة أيضا.

يمكنك وضع الصفوف من Invoiceticket في جدول مؤقت، ثم حذف Invoiceticket وتذكرة وفاتورة أخيرا من المعرفات في الجدول المؤقت. أخيرا تفجير الطاولة المؤقتة.

لا أعرف إذا كانت هذه مدعومة من قبل جميع DBMS، ولكن في MySQL، يمكنك حذفها من الانضمام إلى الجداول. شيء مثل:

DELETE Invoice, Ticket, InvoiceTicket
FROM Invoice, InvoiceTicket, Ticket
WHERE (condition on Ticket) 
  AND Ticket.Id = InvoiceTicket.TicketId 
  AND InvoiceTicket.InvoiceId = Invoice.Id

تمت الإشارة إليه بشكل صحيح أن حذف الفواتير نفسها قد تؤدي إلى مشاكل إذا تمت الإشارة إلى هذه الفواتير عن طريق الفاتورة غير المحذوفة.

أثناء صحيح، أريد أن أشير إلى عدم وجود مكان أقصد أن أقترح (وليس لدي أي مكان وقال في الواقع) ينبغي أن تكون مجموعة الفواتير المحذوفة مساو إلى مجموعة الفواتير التي يمكن العثور على معرفها في أي فواتيريتشيت

إذا قام أي شخص بتفسير رسالتي أن يعني ذلك، أود أن أحذر هؤلاء الأشخاص ضد مخاطر تحقيق الافتراضات بسهولة شديدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top