Rico: Löschabfrage in MySql

Hallöchen,
nochmal zu meiner Frage von Freitag http://forum.de.selfhtml.org/?m=99121&t=17640 :

Es ist lediglich eine 1:m Beziehung, es gibt zwar mehrere Personen, aber jede Person kann nur ihre eigenen Einrichtungen (Kneipen, Diskotheken etc.) verwalten. Gibt es nun aus irgendwelchen Gründen Leichen, wollte ich die mit einem Script löschen lassen, also alle Einrichtungen zu denen es keine Person mehr gibt. Verknüpfung von Tabelle Person und Einrichtung ist durch die Felder Person.id u. Einrichtung.person_id realisiert. Eine elegante Lösung wäre die Einstellung Cascading Delete in der DB, aber leider nicht in MySQL. Mir fehlt ein eleganter SQL-Befehl, wenn es denn geht.

Projekt: http://party.kadiba.de

Cu Rico

  1. Hallo,

    im MS-SQL geht das so:

    delete from tabelle1 where spalte1 not in(select spalte2 from tabelle2)

    alles in tabelle1 wird gelöscht, was sich nicht in der liste, welche durch die unterabfrage entsteht, enthalten ist...

    in MySQL sicher ähnlich...

    Odium

    1. ich denke, da gibt es solche "unter selects" nicht, oder?

      1. schon mal bei mysql.com gekuckt?

        probiers doch mal aus...

        Odium

        1. Moin!

          schon mal bei mysql.com gekuckt?

          ich empfehle zum mysql.de ;-)

          Aber soweit ich weiß ist sowas nicht mit einem SQL-Statement möglich, wahrscheinlich in MySQL4, aber nicht in 3.

          Zur Not mußt DU halt per Select mit Hilfe von Joins die Datensätze auslesen, und dann in einer Schleife DELETEs ausführen.

          Aber ist ja eigentlich egal, einmal ein Script geschrieben, das kannst Du dann immer verwenden, kommt ja aufs selbe raus, ob Du jetzt einmal ein SQL-Statement bastekst, oder ein Script. Sicher, schöner wäre es, aber hier geht es ja nicht um "schöner Programmieren", sondern es sollte funktionieren ;-)

          Grüße
          Andreas

          1. Hallo,

            naja schöner wäre ind diesem fall eben effizienter...

            wenn ich in schleifen testen muss, ob ich löschen darf oder nicht ist das für die db hoher aufwand...

            ein entsprechendes sql-statement das sich kümmert ist sicher das ideale...

            Einfach sagen "es funktioniert" und gut ist reicht nicht aus...

            code sollte robust und effizient sein...

            Odium

            1. Hallo!

              wenn ich in schleifen testen muss, ob ich löschen darf oder nicht ist das für die db hoher aufwand...

              definiere "sehr hoher Aufwand"

              ein entsprechendes sql-statement das sich kümmert ist sicher das ideale...

              das stimmt!

              Einfach sagen "es funktioniert" und gut ist reicht nicht aus...

              code sollte robust und effizient sein...

              Da stimme ich voll und ganz zu, aber das ist ja ein "Wartungsscript", welches nur nhin und wieder auf die DB "losgelassen" wird. Angenommen da stehen 10.000 Einträge in der DB - was ich schon bezweifele - findet das Select-Statement vielleicht 10, womöglich 100 tote Datensätze. Wenn Du jetzt in einer Schleife 100 DELETEs auf die DB losläßt dauert das vermutlich nichtmal eine Sekunde. Was ist das Problem dabei?

              Es ist oft das Problem(auch meins) das man es immer perfekt will, das es auch in einer DB mit mehreren Mio Datensätzen "effizient" funktionieren würde, aber wenn diese Zahel doch sowieso niemals erreichen wird, warum sich dann so viele Sorgen machen, außerdem wäre die einzige Alternative auf eine andere RDBMS umzustellen, und ob sich das lohnt?

              Grüße
              Andreas

              Odium

              1. Hallo,

                Da stimme ich voll und ganz zu, aber das ist ja ein "Wartungsscript", welches nur nhin und wieder auf die DB "losgelassen" wird. Angenommen da stehen 10.000 Einträge in der DB - was ich schon bezweifele - findet das Select-Statement vielleicht 10, womöglich 100 tote Datensätze. Wenn Du jetzt in einer Schleife 100 DELETEs auf die DB losläßt dauert das vermutlich nichtmal eine Sekunde. Was ist das Problem dabei?

                Wobei mir "wenn aus irgendwelchen Gründen Leichen entstehen" (siehe Originalposting) schon zu denken gibt. Der eigentliche Fehler liegt IMHO im bestehenden Code. Das was hier diskutiert wird, ist eigentlich Verschleierungsmethodik.

                Es ist oft das Problem(auch meins) das man es immer perfekt will, das es auch in einer DB mit mehreren Mio Datensätzen "effizient" funktionieren würde, aber wenn diese Zahel doch sowieso niemals erreichen wird, warum sich dann so viele Sorgen machen, außerdem wäre die einzige Alternative auf eine andere RDBMS umzustellen, und ob sich das lohnt?

                Grundsätzlich bin ich auch für die Verhältnismäßigkeit zwischen Aufwand und Zweck. Allerdings habe ich die Erfahrung gemacht, daß genau diese Argumentation al Rechtfertigung für"Huschpusch"-Lösungen herangezogen wird. Meist ist etwas mehr Sorgfalt bei jeder Zeile, die man schreibt, schon der richtige Ansatz.

                Und noch eine Bemerkung zur Wahl der Mittel: Eine Datenbank, die keine Constraints und Transaktionen unterstützt, würde ich nur sehr, sehr  vorsichtig einsetzen, da die Gefahr von Dateninkonistenzen praktisch schon mit gelifert ist. Wobei allein das Wissen um die Gefährlichkeit dieser Mängel auch schon ausreichen kann, entsprechend defensiv zu programmieren.

                Grüße
                  Klaus

                1. Hallo!

                  Wobei mir "wenn aus irgendwelchen Gründen Leichen entstehen" (siehe Originalposting) schon zu denken gibt. Der eigentliche Fehler liegt IMHO im bestehenden Code. Das was hier diskutiert wird, ist eigentlich Verschleierungsmethodik.

                  Da hast Du Recht!

                  Grundsätzlich bin ich auch für die Verhältnismäßigkeit zwischen Aufwand und Zweck. Allerdings habe ich die Erfahrung gemacht, daß genau diese Argumentation al Rechtfertigung für"Huschpusch"-Lösungen herangezogen wird. Meist ist etwas mehr Sorgfalt bei jeder Zeile, die man schreibt, schon der richtige Ansatz.

                  Ja, das stimmt, aber in diesem Fall geht es wohl nicht anders als von mir beschrieben, oder?

                  Und noch eine Bemerkung zur Wahl der Mittel: Eine Datenbank, die keine Constraints und Transaktionen unterstützt, würde ich nur sehr, sehr  vorsichtig einsetzen, da die Gefahr von Dateninkonistenzen praktisch schon mit gelifert ist. Wobei allein das Wissen um die Gefährlichkeit dieser Mängel auch schon ausreichen kann, entsprechend defensiv zu programmieren.

                  Ja ein interessantes Thema. Ich benutze grundsätzlich keine Transaktionsttabellen in MySQL, obwohl es diese ja gibt. Ich habe das im Manual mal kurz angelesen, war aber irgendwie zu kompliziert.
                  Wenn ich Transaktionstabellen verwende, was habe ich dann für einen Vorteil? Wennich alle Afbragen so lasse wie sie sind habe ich doch überhaupt keinen Vorteil, oder? Der Sinn von Transaktionen ist doch, das beim Scheitern einer Abfrage alles wieder rückgängig gemacht wird, oder? Aber wenn ich "normal" was eintrage kann ich doch auch prüfen ob s erfolgreich war und reagieren, das geht ja mit Transaktionen auch nicht automatisch. Und ist der Fall so wahrscheinlich, das wenn ich mehrere Inserts mache, das dann eine davon fehlschlägt und ich alles Rückgängig  machen muß? Irgendwie ist mir der echte Vorteil von Transaktionen noch nicht ganz klar.

                  Grüße
                  Andreas

                  Grüße
                    Klaus

                  1. Danke trozdem.

                    Natürlich wird beim normalen löschen (d.h. für den Anwender) auch die "ChildTabellen"-Einträge gelöscht. Für Admin-Wartungsaufgaben wollte ich dann aber für evtl. Löschen von Einträgen "einfache" Delete-Anweisungen benutzen und zum Schluss immer eine Checkrotine für Inkonsiszenten laufen lassen. Zudem sollen dabei auch Bilddateien, die in der DB nicht mehr vorhanden bzw. gesperrt sind, auf der Festplatte gelöscht werden. Aus Performancegründen ist das also egal, wie schon erwähnt WARTUNGSSCRIPT. Warten wir mal auf die Einführung v. MySQL4.x

                    Cu Rico

                  2. Hallo,

                    Grundsätzlich bin ich auch für die Verhältnismäßigkeit zwischen Aufwand und Zweck. Allerdings habe ich die Erfahrung gemacht, daß genau diese Argumentation al Rechtfertigung für"Huschpusch"-Lösungen herangezogen wird. Meist ist etwas mehr Sorgfalt bei jeder Zeile, die man schreibt, schon der richtige Ansatz.
                    Ja, das stimmt, aber in diesem Fall geht es wohl nicht anders als von mir beschrieben, oder?

                    Ich denke, daß DU da schon ziemlcih richtig liegst, allerdings ändert das nichts an der Tatsache, daß diese nachträgliche Löscherei ein ganz anderes Problem verschleiert.

                    Wenn ich Transaktionstabellen verwende, was habe ich dann für einen Vorteil?

                    Nehmen wir vorliegenden Fall. Da will einer eine PErson löschen, dabei sollten alle verknüpften Einträge aus den anderen Tabellen mit entfernt werden. Dadurch ergibt sich, daß mehr als ein Lösch-Statement abgesetzt werden muß, um diesen Vorgang vollständig durchzuführen.
                    Wird auch nur eines nicht ausgeführt, da irgendein Fehler aufgetreten ist, dürften alle anderen auch nicht ausgeführt werden, da es sonst zu Inkonsistenzen in der Datenbank kommt. Was nun, wenn es dummerweise nicht das erste Statement ist, daß da abkracht? Dumme Sache, der Datensatz ist weg, unwiderbringlich futsch.
                    Damit Das nicht passiert, setzt man auf die sog. Transaktionen. Dabei merkt die Datenbank die Aktionen nur vor, für die aktuelle DB_sitzung werden die Daten auch dementsprechend korrigiert verwaltet, und erst wenn alle Statements fehlerfrei ausgeführt wurden, werden die Änderungen auch bestätigt (commit). Sollte ein Fehler aufgetaucht sein, dann wird der Original-Zustand wieder hergestellt, so als ob nie ein Statement abegsetzt wurde (rollback).

                    In dem hier diskutierten Falle könnte die Anwendung also einmal alle Statements durchführen, wenn es nicht geklappt hat, dem Anwender mitteilen, wo und warum es nicht funktioniert hat, und den Originalzustand wieder herstellen. Es gibt dann nur mehr zwei Möglichkeiten:
                    Entweder es gibt eine Person mit allfälligen Terminen, oder es gibt weder Person noch die zugehörigen Termine. TErmine, die nicht existierenden PErsonen gehören sind ausgeschlossen.

                    Und ist der Fall so wahrscheinlich, das wenn ich mehrere Inserts mache, das dann eine davon fehlschlägt und ich alles Rückgängig  machen muß?

                    Öfter als Du jetz annimmst. Es gibt so viele Gründe, warum ein Statement nicht funktioniert, da ist es schon ein Wunder, wenn überhaupt noch was in eine Datenbank kommt *g*.

                    Grundsätzlich sollten zwei oder mehrere zusammengehörende Statements mittels Transaktionen geschützt werden, sofern die Datenbank das unterstützt. Es kostet zwar etwas an Datenbank-Performance, allerdings macht eine bessere Datenkonsistenz IMHO das wieder locker wett.

                    Grüße
                      Klaus

        2. du scheinst recht zu haben... sub-selects werden wohl erst ab version 4.1 unterstützt...

          das ist schlecht...

          so musst du wohl über php gehen...

          mit distinct das kriterium aus der 2. tabelle auslesen

          die erste tabelle hernehmen, kucken ob das feld ungleich der vorherausgewählten liste ist
          ggf. löschen...
          zum nächsten eintrag in der ersten tabelle

          das ist aber enorm ungünstig, weiß nicht ob das noch besser geht...

          Odium