Rekursives Löschen von Datenbankeinträgen

qsrs

Erfahrenes Mitglied
Hallo,

ich habe ein Skript in das ich eine Funktion einbauen möchte, um Datenbankeinträge rekursiv zu löschen. Dabei geht es um Kategorien und Unterkategorien. Die Tabellenstruktur ist simpel:

id | name | directory_id
1 | kat_1 | 0
2 | sub_1 | 1
3 | sub_2 | 2

Das erzeugt folgende Hierarchie:
kat_1
- sub_1
- - sub_2

So kann ich eine theoretisch unendlich weite Kategorietiefe erreichen. Nun ist das Problem bzw. die Frage, wie ich rekursiv Löschen kann. D.h. wenn ich eine Kategorie lösche, dass deren Unterkategorien, sowie deren evtl. vorhandenen Unterkategorien ebenfalls gelöscht werden. Eine weitere Schwierigkeit besteht darin, dass ich eine Tabelle habe, in der Dateinamen gespeichert werden, die zu den Kategorien und Unterkategorien gehören (der Bezug erfolgt über die id), die bei einem Löschvorgang einer Kategorie, ebenfalls gelöscht werden müssen, natürlich auch die, die in evtl. bestehenden Unterkategorien vorhanden sind. Mir fehlt hier im Moment der Ansatz und ich würde mich über Hilfe wirklich sehr freuen. Ich kann keine Nested Sets verwenden. Die Vorgabe ist, es rekursiv zu bearbeiten. Vielen Dank für evtl. Hilfe.
 
Du hast das Problem ja schon quasi selbst gelöst. Erstelle eine Funktion, die erstmal ausliest, ob von einer Kategorie einer Unterkategorie existiert. Wenn das der Fall ist, ruft sich die Funktion selbst noch einmal auf und das gleiche Spiel wird endlos weiter vollzogen, bis die unterste Kategorie gefunden wurde (es gibt keine Unterkategorien mehr). Nach der Prüfung auf Unterkategorie (immer noch innerhalb der Funktion kannst du die aktuelle Kategorie löschen. Ich schreib ma Pseudocode:

Code:
funktion loescheKategorieRekursiv( $kategoriename )
{
    $ergebnis = query("SELECT kategoriename FROM kategorien WHERE vater = $kategoriename");
    solange($ergebnis als $kategorie) {
        loescheKategorieRekursiv($kategorie);
    }
    query("DELETE FROM kategorien WHERE kategoriename = $kategoriename");
}

So in der Art halt...
 
Ich benötige dazu doch genauere Anhaltspunkte, es ist mir von der Logik her fast klar, aber mir fehlt der Ansatz um es umzusetzen. Würde das nicht auch mit einer for- oder whlie-Schleife gehen?
 
Vielen Dank für den Hinweis, aber nein, ich muss es leider vollständig in PHP realisieren, ich habe ja unter anderem aucn noch eine Zweittabelle, in denen Datensätze stehen, die ebenfalls gelöscht werden sollen, die einen Bezug zu den Kategorien haben.
 
Hallo qsrs,

schade.

Deine zusätzliche Tabelle (Dateien?) hat ja offenbar genauso eine Fremdschlüsselbeziehung zu den Kategorien. Spricht nichts dagegen, diese genauso zu definieren:

Angenommen dein Primärschlüssel auf directory sitzt auf ID:

1. Anlegen eines Foreign Keys mit Löschweitergabe, der dafür sorgt, dass Unterkategorien automatisch gelöscht werden:
SQL:
ALTER TABLE directory 
  ADD CONSTRAINT fk_parent_directory FOREIGN KEY (directory_id)
  REFERENCES directory (id) ON DELETE CASCADE;

2. Anlegen des Foreign Keys mit Löschweitergabe auf der Datei-Tabelle, der dafür sorgt, dass eventuell zugeordnete Dateien beim Löschen einer Kategorie automatisch mit gelöscht werden:
SQL:
ALTER TABLE dateien
  ADD CONSTRAINT fk_directory FOREIGN KEY (categorie_id)
  REFERENCES directory (id) ON DELETE CASCADE;

Das RDBMS sollte diese Bezüge in beliebiger Komplexität selbst verwalten können, sonst entstehen schnell "Leichen" oder Duplikate.

Was nun bleibt ist ein Aufruf von:

SQL:
DELETE FROM directory WHERE id = 1

Damit werden
1. automatisch alle Unterkategorien gelöscht,
2. automatisch alle eventuell vorhandenen Dateien gelöscht, die irgendeiner Kategorie, die durch Schritt 1 gelöscht würde, zugeordnet waren


Wenn es denn allerdings tatsächlich ein PHP-Skript sein soll, fährst du mit eine rekursiven Funktion sicher am besten.

Markus
 
Zuletzt bearbeitet:
Nochmals vielen Dank für diese Hilfe. Ich werde das sicher noch anderweitig verwenden können, in diesem Fall benötige ich jedoch eine rekursive Abfrage mittels PHP. Das ist aus verschiedenen Gründen der Fall. Ich muss z.B. mit unlink (); auch die Dateien löschen, und das kann ich ja nur mit PHP.

Ich bin noch nicht so weit, dass ich das komplett selbst umsetzen kann, ich wäre über jede Hilfe sehr dankbar.
 
Zurück