Raiko: Error 1062 behandeln

Hallo,

ich habe einen kombinierten Unique Index in einer Tabelle 'a' auf 2 Spalten.

Wenn ich nun aus einer 2. Tabelle 'b' selber Struktur alle Einträge in die a-Tabelle kopieren will, bricht der Vorgang natürlich an der Stelle ab, wo ein Error 1062 vorliegt.

Die Query hierzu ist nach der Art:

INSERT INTO a 
( Spalte1,
Spalte2,
Spalte3
 )
SELECT 
Spalte1,
Spalte2,
Spalte3
FROM b

Frage: Wie habe ich auf diese Art überhaupt eine Chance, einen 1062er zu behandeln? Ich erhalte eigentlich doch nur eine Antwort, ob es insgesamt funktioniert oder nicht. In einer Schleife könnte ich bei jedem Eintrag prüfen, ob er kopiert wird entsprechend weiter verfahren. Aber auf diese Art kann ich den Fehler 1062 nicht individuell behandeln. Oder sehe ich das falsch? Dann bitte ich um Hilfe, wie ich den Fehler abfange und behandeln kann.

Raik

  1. ich habe einen kombinierten Unique Index in einer Tabelle 'a' auf 2 Spalten.

    Wenn ich nun aus einer 2. Tabelle 'b' selber Struktur alle Einträge [mit einem SQL-Befehl] in die a-Tabelle kopieren will, bricht der Vorgang natürlich an der Stelle ab, wo ein Error 1062 vorliegt.

    Frage: Wie habe ich auf diese Art überhaupt eine Chance, einen 1062er zu behandeln?

    Du bekommst eine Fehlermeldung, in der eigentlich auch der Wert stehen sollte, der den Fehler verursacht. Wie diese Meldung nun bei dem von dir verwendeten Programm bzw. der verwendeten Programmiersprache gehandhabt wird, lässt sich ohne Kenntnis derselben nicht sagen.

    Alternativ könntest du dir vor dem Kopieren sämtliche Zeilen in der Zieltabelle heraussuchen, die mit jenen der Quelltabelle kollidieren würden. Mit diesem Wissen bereitest du entweder das Ziel vor oder nutzt es, um die betreffenden Zeilen vom Kopierbefehl auszuschließen. Letzteres könntest du auch in einem Rutsch erledigen, also die Suche in den Kopierbefehl einbauen.

    Jeden Datensatz einzeln zu kopieren, erscheint mir eher als die schlechteste Lösung.

    PS: Es wäre hilfreich, wenn du bei solchen Fragen nicht nur Zahlen verwendest, deren Bedeutung man sich erstmal raussuchen muss ("1062"), sondern einfach den Fehler nennst ("Eintrag kollidiert mit eindeutigem Index"). Deine Frage hat ja erstmal wenig bis gar nichts mit MySQL zu tun, insofern sind MySQL-Fehlercodes eher ein Hindernis.

    1. Hi,

      Alternativ könntest du dir vor dem Kopieren sämtliche Zeilen in der Zieltabelle heraussuchen, die mit jenen der Quelltabelle kollidieren würden. Mit diesem Wissen bereitest du entweder das Ziel vor oder nutzt es, um die betreffenden Zeilen vom Kopierbefehl auszuschließen. Letzteres könntest du auch in einem Rutsch erledigen, also die Suche in den Kopierbefehl einbauen.

      Ja, das ist eine gute Idee.

      Raik

  2. Hi,

    Wenn ich nun aus einer 2. Tabelle 'b' selber Struktur alle Einträge in die a-Tabelle kopieren will, bricht der Vorgang natürlich an der Stelle ab, wo ein Error 1062 vorliegt.

    Du könntest die entsprechenden Datensätze von vornherein ausschließen:

    AND NOT EXISTS(select * from Tabelle_A aa WHERE aa.spalte1 = b.spalte1 and aa.spalte2 == b.spalte2)

    cu,
    Andreas a/k/a MudGuard

    1. Du könntest die entsprechenden Datensätze von vornherein ausschließen:

      AND NOT EXISTS(select * from Tabelle_A aa WHERE aa.spalte1 = b.spalte1 and aa.spalte2 == b.spalte2)

      Jein. Er muss ZUNÄCHST EINMAL entscheiden, ob er die Datensätze mit bereits vorhandenen IDs übergeht (das genau ist Dein Vorschlag) oder ob im Falle doppelt vorhandener Keys ein Update machen will:

      INSERT ... ON DUPLICATE KEY UPDATE

      1. Hi,

        INSERT ... ON DUPLICATE KEY UPDATE

        das wäre interessant, wenn ich es an einen "Spaltenbedingung" (wenn spalte8 des neuen Datensatzes größer als Spalte8 des vorhandenen Datensatzes) knüpfen könnte.

        Raik

        1. Hallo Raiko,

          das wäre interessant, wenn ich es an einen "Spaltenbedingung" (wenn spalte8 des neuen Datensatzes größer als Spalte8 des vorhandenen Datensatzes) knüpfen könnte.

          Aha, warum denn nicht gleich, es gibt also ein Diskriminierkritierium.

          Die folgende Query liefert Dir die Schlüsselwerte plus den größeren der beiden Werte aus Spalte 8:

          select key1, key2, max(spalte8)
          from tabelleB
          group by key1, key2
          

          Und damit kannst Du nun einen Filter bauen, der nur die Sätze aus Tabelle B darstellt, in denen Spalte8 den Maximalwert aufweist:

          insert into tabelleA
          select b.key1, b.key2, 
          from tabelleB b JOIN (select key1, key2, max(spalte8) as max8
                                from tabelleB
                                group by key1, key2) f
                          ON  b.key1 = f.key1
                          AND b.key2 = f.key2
                          AND b.spalte8 = f.max8
          

          Das ist relativ alte Technik und funktioniert auch noch auf MySQL 5.6 (ein neueres hab ich grad nicht hier...).

          Unter MySQL 8 sollten Dir auch Window-Funktionen helfen können.

          Rolf

          --
          sumpsi - posui - obstruxi
      2. Du könntest die entsprechenden Datensätze von vornherein ausschließen:

        AND NOT EXISTS(select * from Tabelle_A aa WHERE aa.spalte1 = b.spalte1 and aa.spalte2 == b.spalte2)

        Ich habe mich jetzt dazu entschieden, Doppel aus der CopySource-Tabelle in eine Delete-Tabelle zu verschieben und auch Doppel bezogen auf die CopyDestination-Tabelle.

        INSERT INTO tabelle_Del
        ( Spalte1,
        Spalte2,
        Spalte3
        uid)
        SELECT 
        Spalte1,
        Spalte2,
        Spalte3
        FROM tabelle_CopySource t
        WHERE 
        ((Spalte1, Spalte2) 
        IN 
        (SELECT Spalte1, Spalte2
            FROM tabelle_CopySource
            GROUP BY Spalte1, Spalte2
            HAVING COUNT(*) > 1))
        OR
        (EXISTS
        (select * from tabelle_CopyDest aa 
        WHERE 
        aa.Spalte1 = t.Spalte1 AND aa.Spalte2 = t.Spalte2)
        )
        
        

        Gibts irgendeinen Kniff, sie auch direkt aud der CopySource zu löschen oder muß ich dazu noch eine eigene Query machen?

        Raik

        1. Gibts irgendeinen Kniff, sie auch direkt aud der CopySource zu löschen oder muß ich dazu noch eine eigene Query machen?

          Vor allem stelle ich gerade fest, dass bei einer Delete-Query im Gegensatz zu einer Insert-Query an der Stelle

          WHERE 
          aa.Spalte1 = t.Spalte1 AND aa.Spalte2 = t.Spalte2
          

          t unbekannt ist.

          Raik

          1. Hi,

            Vor allem stelle ich gerade fest, dass bei einer Delete-Query im Gegensatz zu einer Insert-Query an der Stelle

            WHERE 
            aa.Spalte1 = t.Spalte1 AND aa.Spalte2 = t.Spalte2
            

            bei Delete/Update kann man nicht mit join arbeiten, da muß man subqueries verwenden, wenn mehr als eine Tabelle für die Bedingung gebraucht wird.

            cu,
            Andreas a/k/a MudGuard

            1. Hi,

              bei Delete/Update kann man nicht mit join arbeiten, da muß man subqueries verwenden, wenn mehr als eine Tabelle für die Bedingung gebraucht wird.

              Jaja, ich weiß. Aber ich habs auch mit Subquery versucht. Ging genauso wenig. Hast Du mal nen Link da, wie man das löst?

              Raik

    2. Hi,

      AND NOT EXISTS(select * from Tabelle_A aa WHERE aa.spalte1 = b.spalte1 and aa.spalte2 == b.spalte2)

      Da ist Dir ein Doppelgleich in den Code gerutscht.

      Klar, das könnte ich machen. Dann aber geht mir die Information flöten, welche Datensätze aussortiert werden.

      Raik