Error 1062 behandeln
Raiko
- mysqli
- sql
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
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.
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
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
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
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
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
Da hätte ich die Lösung anzubieten, erst einmal (wie von Mudguard gezeigt) die bereits vorhandenen Datensätze zu ignorieren, und sodann das „von-Tabelle-zu-Tabelle-Update“ zu machen, wie hier vorgeschlagen.
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
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
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
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
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