Daniel: verschachteltes MySQL-Query

Ahoi alle,

war schon fitter in SQL und hab grad etwas probleme ein verschachteltes Query hinzubekommen.

-------------
|    tab1   |  Tabelenname
-------------
|kat_id|name|  Spaltennamen
-------------
| X    |  y |  Daten

-------------
| kategorien|  Tabelenname
-------------
|  id  | kat|  Spaltennamen
-------------
| X    |  y |  Daten

ich möchte aus der tab 1 alle einträge deren kategorie ID (nicht) im kategorientable ist selektieren (und löschen)

Hintergrund, bei der programmierung des tolls das die einträge macht wurde nicht berücksichtigt das wenn eine kategorie gelöscht wird auch die dazu gehörigen einträge aus Tab1 gelöscht werden.

SELECT * FROM tab1 WHERE kat_id IN SELECT id FROM kategorien

funktioniert nicht :(

MfG

  1. Hallo Daniel !

    Mal ein paar Dinge vorab:

    • kat_id ist ein Fremdschlüssel.
        Bei der Datendefinition ("CREATE TABLE tab1 ... FOREIGN KEY kat_id REFERENCES kategorien(id)") kann angegeben werden ob
        abhängige Datensätze (in tab1) beim Löschen eines Satzes mitgelöscht werden sollen (Zusatz "ON DELETE CASCADE" ) oder das Löschen des Satzes aus kategorien ganz verhindert werden soll (Zusatz "ON DELETE RESTRICT" )
      Wenn, wie hier offenabr keine der beiden Möglichkeiten zum Tragen kommt kann es sein, dass entweder
    • Die Tabelle tab1 eine (MYSQL)MyISAM Tabelle ist; MyISAM verwaltet solche Beziehungen nicht; MySQL kennt hierzu den Typ "InnoDB"
    • Die Fremdschlüssel auf NULL gesetzt wurden

    Der resultierende Effekt kann aber vom Entwickler der Datenbank durchaus beabsichtigt sein !!!
    Also : Vorsicht !
    ;-)

    "SELECT * FROM tab1 WHERE kat_id IN SELECT id FROM kategorien;"

    Das loescht nicht wirklich und ist syntaktisch falsch.

    "SELECT * FROM tab1 WHERE kat_id IN (SELECT id FROM kategorien);"
    Das ist syntaktisch richtig, selektiert aber falsch.

    "SELECT * FROM tab1 WHERE kat_id NOT IN (SELECT id FROM kategorien);"
    Das ist syntaktisch richtig und selektiert richtig, loewscht aber nicht...

    => "DELETE FROM tab1 WHERE kat_id NOT IN (SELECT id FROM kategorien);"
    => "COMMIT;"

    ...und das ist das was Du suchst.
    ;-)

    Grüsse

    hkl

    funktioniert nicht :(

    MfG

    1. Ahoi _hkl,

      Der resultierende Effekt kann aber vom Entwickler der Datenbank durchaus beabsichtigt sein !!!
      Also : Vorsicht !

      Der entwickler ist wohl eher das entwickler da die tabellen durch ein CMS erstellt werden.

      "SELECT * FROM tab1 WHERE kat_id IN SELECT id FROM kategorien;"
      Das loescht nicht wirklich und ist syntaktisch falsch.

      Das weiss ich auch *g*, ich wollte zuvor nur mal ein Select machen damit ich sehe ob es funktioniert, die richtigen datansätze selektiert werden. die Syntax war mein problem, das ich NOT IN anstatt IN machen muss und DELET anstatt SELECT * war mir klar. trotzdem danke.

      Vielen dank für deine mühen

      MfG

      1. Ahoi _hkl,

        Hallo vom Festland !

        Das weiss ich auch *g*, ich wollte zuvor nur mal ein Select machen damit ich sehe ob es funktioniert, die richtigen datansätze selektiert werden. die Syntax war mein problem, das ich NOT IN anstatt IN machen muss und DELET anstatt SELECT * war mir klar. trotzdem danke.

        Wenn Dir das alles klar ist, warum postest Du dann ein falsches Statement ?

        Wenn Du ene Lösungs suchst solltest Du immer Deinen Code so origianlgetreu wie möglich zitieren.

        Grüsse

        Holger

        Vielen dank für deine mühen

        MfG

        1. Ahoi _hkl,

          Wenn Dir das alles klar ist, warum postest Du dann ein falsches Statement ?

          Weil ich im Kopf so vorgegangen bin. bzw. so vorgehen wollte/will. erstmal ein select damit ich seh das die richtigen selektiert werden. Dann aus dem SELECT ein DELETE und es passt,... Hoffe du hast meinen vorhergehenden Post nicht als angriff gewerttet, bin dir wirklich dankebar für deine Mühen.

          Wenn Du ene Lösungs suchst solltest Du immer Deinen Code so origianlgetreu wie möglich zitieren.

          Werd ich mir für die Zukunft merken.

          MfG

    2. Ahoi _hkl,

      => "DELETE FROM tab1 WHERE kat_id NOT IN (SELECT id FROM kategorien);"
      => "COMMIT;"

      ich hab MySQL 4.0.22

      Es scheint dort nicht zu funktionieren. denn phpMyAdmin bringt:

      --------------------------------------
      Fehler

      SQL-Befehl: Dokumentation

      DELETE FROM tab1 WHERE kat_id NOT IN (
      SELECT id
      FROM kategorien
      )

      MySQL meldet: Dokumentation
      #1064 - You have an error in your SQL syntax.  Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT id
      FROM kategorien
      )' at line 2
      ---------------------------------------

      bin grad in der Docu am schaun und rumprobieren ob ichs gelöst bekomm. Für hilfe bin ich trotzdem dankbar

      MfG

      1. Hallo Daniel,

        => "DELETE FROM tab1 WHERE kat_id NOT IN (SELECT id FROM kategorien);"

        ich hab MySQL 4.0.22
        Es scheint dort nicht zu funktionieren.

        natürlich nicht. Subselects unterstützt MySQL erst ab Version 4.1, siehe Handbuchabschnitt Subqueries.

        Nutze Iljas Vorschlag mit dem LEFT JOIN.

        Freundliche Grüße

        Vinzenz

        1. Ahoi Vinzenz Mai,

          für das SELECT ok, das funktioniert mit dem LeftJoin immerhin, aber DELETE kommt Syntax error, was verständlich ist denn es wird ja somit eine temporäre Tabelle erstellt, wie soll man daraus löschen können?

          Ich glaube mit einem einzeiler ist es nicht getan,.... Wenn es nicht 1057 insgesamt wären dann würd ich das ja händisch machen,... IP merken DELETE FROM tab WHERE id=xy

          MfG

        2. Nutze Iljas Vorschlag mit dem LEFT JOIN.

          Besser nicht, denn wenn der Fragesteller daraus ein DELETE macht löscht er genau die falsche Teilmenge, namelich diejenigen Sätze die einen validen Datensatz referenzieren und nicht die Karteileichen.

          ;-)

          Freundliche Grüße

          Vinzenz

          1. Ahoi _hkl,

            Besser nicht, denn wenn der Fragesteller daraus ein DELETE macht löscht er genau die falsche Teilmenge, namelich diejenigen Sätze die einen validen Datensatz referenzieren und nicht die Karteileichen.

            Vor dem DELETE hab ich ein SELECT gemacht und das scheint richtig zu sein. als ich ein DELETE daraus machen wollte bekam ich einen Syntax fehler,... Selektiert werden sehr wohl die karteileichen,...

            MfG

            1. yo,

              schau dir mal die doku an, delete bei mehreren tabellen. mit dem sollte es dir gelingen, das SELECt umzuschreiben.

              [Link:http://dev.mysql.com/doc/refman/5.1/de/delete.html]

              Ilja

              1. Ahoi Ilja,

                schau dir mal die doku an, delete bei mehreren tabellen. mit dem sollte es dir gelingen, das SELECt umzuschreiben.

                VIELEN DANK. ich hatte sie gestern schon angeschaut aber ich stand wohl gestern etwas neben der Kappe und es hat mir nix gebracht :( Heute hats aber was gebracht, der datenmüll ist weg. Vielen dank!!!!!

                MfG

          2. Nutze Iljas Vorschlag mit dem LEFT JOIN.

            Besser nicht, denn wenn der Fragesteller daraus ein DELETE macht löscht er genau die falsche Teilmenge, namelich diejenigen Sätze die einen validen Datensatz referenzieren und nicht die Karteileichen.

            Man streiche main letztes Geschwafel; ich hatte die "IS NULL" Klausel übersehen.

            Grüsse
            hkl

            ;-)

            Freundliche Grüße

            Vinzenz

  2. yo,

    ich möchte aus der tab 1 alle einträge deren kategorie ID (nicht) im kategorientable ist selektieren (und löschen)

    SELECT * FROM tab1 WHERE kat_id IN SELECT id FROM kategorien
    funktioniert nicht :(

    SELECT *
    FROM TAB1 t
    LEFT JOIN kategorien k ON k.id = t.kat_id
    WHERE k.id IS NULL
    ;

    Ilja

  3. Ahoi alle,

    vielen dank für eure hilfe, stand gestern etwas aufm schlauch aber jetzt hats ja geklappt.

    MfG