In python ein update auf mysql -> Safe Mode?!?

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Hallo Leute,

ich habe nicht direkt mit python ein Problem sondern aus Python heraus mit mysql.
Ich hoffe das ihr mir trotzdem helfen könnt. Ansonsten könnt ihr mir ja ein gutes deutschsprachiges MySQL-Forum empfehlen (falls das nötig sein wird).

Jedenfalls habe ich viele Tabellen. Ich hoffe korrekt erstellt und funktioniert auch alles wunderbar.
Eine Tabelle davon hat jedoch keinen alleinigen Key (wie die meisten anderen die ein AI-Feld ('id') besitzen) sondern zwei 'Subkeys' die zusammen immer eindeutig (unique) sind. Es ist sozusagen eine 'Auflösungstabelle'. Es ist auch einen Uniqe-Key mit diesen 2 Feldern definiert.
So, beim inserten und select funktioniert auch alles prima, doch leider beim updaten bekomme ich immer einen Fehler in mySQL (Error 1175).
Der besagt folgendes:
Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode..
Dazu gibt es ein Workaround indem ich den SAFE-MODE zuallererst deaktiviere und im Anschluss wieder aktiviere.
Das ist für mich aber irgendwie 'hingewurstelt'. Ich würde gerne in der WHERE-Klausel die Keys definieren damit mysql dann erkennt das die KEY-Regel eingehalten wird.
Wie mache ich das aber mit einem, ich nenne es mal 'multikey' (also den 2 Feldern die zusammen ein Unique darstellen)?
Zu allem Übel kommt noch hinzu das ich ein 'Inner Join' habe welcher auf eine andere Tabelle verknüpft. Der ist aber richtig verknüpft indem ich im 'ON'-Statement beide Subkeys (also mein 'multikey') verknüpfe. Im Select-Statement (zur Probe) funktioniert auch alles wunderbar.

Kann mir mal jemand helfen und sagen wie er das macht in mySQL wenn er ein update auf Tabellen macht die so ein Multikey haben?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@kaineanung: sinnvoll wäre jetzt noch, wenn Du die Tabellendefinitionen und das UPDATE-Statement posten würdest.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Ach so, ja klar!

Hier der Updatebefehl:

[Codebox=mysql file=Unbenannt.sql]
update
soccer_card s_card inner join soccer_matchday_player s_mdp on s_mdp.matchid = s_card.matchid and s_mdp.player = s_card.player
set s_mdp.parttime = s_card.card_time
where s_card.card > 1
[/Codebox]

Und hier die Tabellendefinitionen:

Spieltag-Spieler-Tabelle:
[Codebox=mysql file=Unbenannt.sql]
DROP TABLE IF EXISTS soccer_matchday_player;
CREATE TABLE `soccer_matchday_player` (
`matchid` int(10) DEFAULT NULL,
`player` int(10) unsigned NOT NULL,
`team` int(10) unsigned NOT NULL,
`round` int(11) DEFAULT NULL,
`league` int(11) NOT NULL,
`date` date NOT NULL,
`no` int(2) DEFAULT NULL,
`parttime` int(3) DEFAULT NULL,
`begin_status` varchar(1) DEFAULT 'p',
KEY `multikey` (`matchid`,`player`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
[/Codebox]

Verwarnungs-Tabelle (Kartentabelle)
[Codebox=mysql file=Unbenannt.sql]
DROP TABLE IF EXISTS soccer_card;
CREATE TABLE `soccer_card` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`matchid` int(11) NOT NULL,
`player` int(11) NOT NULL,
`card_time` int(11) NOT NULL,
`card` int(2) unsigned NOT NULL,
`reason` int(11) NOT NULL,
`team` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
[/Codebox]

So, nach dem Befüllen von der Spieltags-Spieler-Tabelle und der Verwarnungstabelle, will ich nun die Spielzeiten der Spieler aktualisieren. Wer früher vom Platz geflogen ist, dem wird der Zeitpunkt des Platzverweises als Spielzeit aktualisert (dieser Spieler ging ja nicht über die 'volle Distanz').
Komischerweise habe ich das Gleiche mit den Auswechslungen nur das ich dort über 3 Tabellen verknüpfe. Dort hat es nach anfänglicher Schwierigkeit (auch der Error 1175) aber plötzlich geklappt OHNE daß ich den Safemode deaktivieren musste.
Im o.g. Beispiel klappt das nur wenn ich den SAFE-MODE deaktivere. Aber das Ergebnis stimmt dann schon. Ich würde aber sehr sehr gerne 'sauberen' Code haben statt dieses 'Quick & Dirty' zu verwenden. Es hat ja auch einen Sinn das der SAFE-MODE eingeführt wurde.... und ich glaube diesen auch zu kennen. Aber mir erschliesst es sich halt nicht wieso dieser bei meinem Code 'anspringt' da ich ja die Keys berücksichtige (denke ich zumindest)...

Da ich Python erlernen will habe ich mir ein kleines Projekt überlegt und am naheliegensten wäre halt so ein Semi-Komplexes Ding wie das was ich jetzt mache. Ich hätte aber nicht gedacht das ich mit MySQL Probleme bekomme sondern nur mit Python. Dem scheint wohl nicht so zu sein :(
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Und? Hat sich das mal jemand angeschaut?
Zur Information: an anderer Stelle mache ich auch ein Update auf die gleiche Tabelle nur das ich 2x ein INNER JOIN mache auf andere Tabellen.
Da funktioniert es ohne das ich den SAFE-MODE abschalte?!?
Also an der Tabellendefinitin sollte es nicht liegen.
BlackJack

Ohne mich jetzt mit dem konkreten Problem auseinandergesetzt zu haben: Warum hat `soccer_matchday_player` nur einen Index und keinen Primärschlüssel? Kann es sein dass Du das ``PRIMARY`` vor ``KEY`` vergessen hast? Ich würde ``KEY`` oder ``UNIQUE KEY`` gar nicht erst schreiben denn ``KEY`` ist ausser in ``PRIMARY KEY`` in MySQL ein Synonym für ``INDEX`` was auch mehr dem Standard entsprechen würde wenn ich mich jetzt nicht irre.

Wobei sich dass dann wieder mit dem `matchid` und dort ``DEFAULT NULL`` beisst. Damit sind diese Datensätze ja nicht wirklich gut eindeutig identifizierbar. Die Deklaration dieser Tabelle ist komisch.

Bei den Namen würde ich IDs übrigens konsequent als solche kennzeichnen, also `player_id` statt `player`. Und den Unterstrich würde ich auch bei `matchid` einfügen. Das sind ja zwei Worte. Genau so `parttime` → `part_time`.

`begin_status` kann eine Zeichenkette mit variabler Länge sein wobei die aber maximal 1 sein kann *und* der Wert kann auch NULL sein. Es gibt tatsächlich den Fall das Du eine leere Zeichenkette und NULL unterscheiden können möchtest? Das würde ich ja zu einem festen Zeichen machen, dann kann man NULL und ein Zeichen unterscheiden oder gar NOT NULL und für den ”leer” Fall beispielsweise das Leerzeichen verwenden. Wenn das überhaupt vorkommen kann weil der DEFAULT ja schon ein 'p' ist.

Bei der anderen Tabelle ist das mit der `id` alles ein wenig übertrieben. Bei der Spalte selbst ist NOT NULL nicht nötig wenn man das bei den Constraints am Ende dann zu einem PRIMARY KEY macht, denn da steckt das NOT NULL implizit drin, und auch das UNIQUE was Du danach noch mit einem INDEX auf die `id`-Spalte packst. Selbst dieser INDEX sollte schon in PRIMARY KEY enthalten sein.
Antworten