2016-07-29 27 views
0

Ich schreibe eine C++ - Anwendung in QT Creator auch mit einer SQLite-Datenbankverbindung. Ich möchte erreichen, dass Zeilen aus anderen Tabellen gelöscht werden, wenn ich eine Zeile aus einer Tabelle lösche. Also in meinem Fall, wenn ich eine Zeile aus Basket lösche, werden die Verweiszeilen von Computer ebenfalls gelöscht, dann von Subsystemtabellen, Abonnenten, Regulierungen usw. bis zum Ende.vor dem Löschen triggern geringe Leistung

Hier ist meine Datenbank-Diagramm:

DB Diagram

Ich habe für jede Tabelle erstellt Trigger, die mit einer anderen Tabelle Fremdschlüssel-Referenzen haben.

CREATE TRIGGER delete_fk BEFORE DELETE ON Basket 
FOR EACH ROW BEGIN 
    DELETE FROM Computer WHERE computer.basket = old.id_basket; 
END 

CREATE TRIGGER delete_fk_comp BEFORE DELETE ON computer 
FOR EACH ROW BEGIN 
    DELETE FROM subsystemtable WHERE subsystemtable.computer = id.id_computer; 
END 

CREATE TRIGGER delete_fk_subscriber_map BEFORE DELETE ON subscriber 
FOR EACH ROW BEGIN 
    DELETE FROM mappingtable WHERE mappingtable.subscriber = old.id_subscriber; 
END 

CREATE TRIGGER delete_fk_subscriber_indirect BEFORE DELETE ON subscriber 
FOR EACH ROW BEGIN 
    DELETE FROM indirectsubscriber WHERE indirectsubscriber.subscriber = old.id_subscriber; 
END 

CREATE TRIGGER delete_fk_subscriber BEFORE DELETE ON subscriber 
FOR EACH ROW BEGIN 
    DELETE FROM reserve WHERE reserve.subscriber = old.id_subscriber; 
END 

CREATE TRIGGER delete_fk_subscriber_res BEFORE DELETE ON subscriber 
FOR EACH ROW BEGIN 
    DELETE FROM reserve WHERE reserve.subscriber_res = old.id_subscriber; 
END 

CREATE TRIGGER delete_fk_subs BEFORE DELETE ON subsystem 
FOR EACH ROW BEGIN 
    DELETE FROM subsystemtable WHERE subsystemtable.subsystem = old.id_subsystem; 
END 

CREATE TRIGGER delete_fk_substable_reg BEFORE DELETE ON subsystemtable 
FOR EACH ROW BEGIN 
    DELETE FROM regulations WHERE regulations.subsystem = old.id; 
END 

CREATE TRIGGER delete_fk_substable BEFORE DELETE ON subsystemtable 
FOR EACH ROW BEGIN 
    DELETE FROM subscriber WHERE subscriber.subsystem = old.id; 
END 

Ich bekam, was ich wollte. Und es funktioniert genau so, wie ich es wollte. Aber mein Problem ist jetzt die geringe Leistung. Also in meiner Datenbank habe ich ungefähr 20 Computer für jeden Korb, dann ungefähr 5 Subsysteme für jeden Computer, 100 Subscriber für jedes Subsystem und so weiter. Wenn ich 1 Einzelkorb lösche, dauert die gesamte Prozedur etwa 400 ms. Sollte ich 3 Körbe auf einmal löschen, dauert das bereits mehr als 3 Sekunden.

Ich muss einen Weg finden, damit dies viel schneller funktioniert. Begrenzt um etwa 200-300 ms, schätze ich. Und ich brauche Vorschläge, wie ich das machen kann.

+1

Nehmen Sie ein anderes, ausgereifteres Datenbanksystem? PostgreSQL zum Beispiel. Oder verwenden Sie Fremdschlüssel richtig, wie hier erklärt: https://www.sqlite.org/foreignkeys.html#fk_actions. 'CASCADE'. – maxik

Antwort

2

Sie implementieren Fremdschlüssel manuell. Dies ist nicht notwendig; Sie können einfach ON DELETE actions verwenden, damit die Datenbank die entsprechenden Änderungen vornehmen kann.

Ob Sie Fremdschlüssel manuell oder mit Hilfe der DB implementieren, müssen Sie indexes on certain key columns erstellen, oder alle Suchvorgänge, die verwandt werden, um verwandte Zeilen zu finden, werden langsam sein.

+0

Insbesondere beim Erstellen der Fremdschlüsseleinschränkung sollten Sie die Option ON DELETE CASCADE verwenden. Zum Beispiel, da 'Computer' sich auf' Basket' ​​bezieht, sollten Sie 'id_basket' ​​eine Fremdschlüsselkonstante hinzufügen. Wenn dann eine Zeile in "Basket" gelöscht wird, wird jede Zeile in "Computer", auf die sich "id_basket" bezieht, ebenfalls automatisch gelöscht. Kein Grund, sich mit Triggern herumzuärgern. –

+0

Aus irgendeinem Grund funktioniert ON DELETE CASCADE nicht für mich. Siehe diese Frage: http://stackoverflow.com/questions/38588039/sqlite3-on-delete-cascade-does-not-work. Und ich kann nur SQlite verwenden. @Alvin –

+0

@EgorChubarov: Nicht sicher, was das Problem ist. Sind Sie sicher, dass Sie 'pragma foreign_keys = on' jedes Mal ausführen, wenn Sie eine neue Verbindung zur Datenbank herstellen und dass alles, was mit der DB verbunden ist, dieses Pragma ausführt? –