PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Alles oder nichts bei mehreren Statements



shaq_
07.03.2019, 08:31
Hallo,

angenommen ich habe eine php Website mit einer Registrierung. In meiner MySQL Datenbank befinden sich die Tabellen User und wohntIn.

Ein User kann sich registrieren mit Angabe seines Namen und seines Wohnorts und bestätigt mit einem Button Klick.

https://i.imgur.com/pXpsnEW.png

In PHP würde ich jetzt zwei INSERT Statements benutzen um den User zu registrieren.


INSERT INTO `User` (`Name`) VALUES (AngegebenerName);
INSERT INTO `wohntIn` (`UID`, `Stadt`) VALUES (LAST_INSERT_ID() , AngegebeneStadt);

Jetzt kann es natürlich zu einigen Problemen kommen:



Aus irgendeinem Grund kann der Name nicht in die User Table eingetragen werden. Der zweite Befehl läuft durch. Abgesehen davon dass sich LAST_INSERT_ID() womöglich auf eine ganze andere ID bezieht, die nichts mit einem User zu tun hat, existiert jetzt ein Eintrag in wohntIn, der keinem User zuzuordnen ist.
Der erste Befehl läuft durch und der zweite nicht. Jetzt existiert ein User ohne Wohnort.


Deswegen bin auf der Suche nach so eine "Alles oder nichts"-Aktion. Nur wenn alle Statements fehlerfrei durchlaufen können, sollen sie es auch tun. Scheitert es an einer Stelle, müssen alle bisher ausgeführten Befehle rückgängig gemacht werden.
Instinktiv würde ich vor dem zweiten INSERT prüfen, ob ein Eintrag in USER existiert mit dieser LAST_INSERT_ID(), und falls ja, kann der zweite INSERT durchgeführt werden. So kann man allerdings auch TRUE zurückbekommen, ohne es zu wollen. Wenn z.B. der erste Befehl scheiterte und sich deshalb LAST_INSERT_ID() auf eine ganze andere ID bezieht, die zufällig aber auch die ID eines User ist.
Außerdem könnte das prüfen an sich ja auch scheitern usw...

Ich bin sicher, dass es da schon eine Logik in SQL geben muss, die sich diesem Problem annimmt.

Vielen Dank!

sn0w
07.03.2019, 15:06
1) Wenn du ernsthaft versuchst raw SQL in PHP zu schreiben hast du ganz andere Probleme als oben genannte.
2) Schau dir PDOs oder prepared statements an.
3) http://php.net/manual/de/mysqli.insert-id.php

shaq_
08.03.2019, 07:41
1) Natürlich nicht. War nur zur vereinfachten Darstellung des Problems.
2) Benutze bereits prepared statements
3) Diese Funktion ist mir bekannt

Den Zusammenhang zu meinem Problem sehe ich wohl nicht ganz

Cystasy
08.03.2019, 13:59
Frage: Wieso packst du das umständlich in 2 unterschiedliche?

Einerseits sagst du das du eine Datenbank nutzt, aber in deiner Grafik siehts aus wie 2 Datenbanken in denen 2 mal die id steht.. was denn nun?

ich würde es so lösen..



id, city
-------------
0, Brandenburg
1, Berlin
2, Hinterm Hof
3, Moep


etc.

quasi..



INSERT INTO deinedb (id, city) VALUES ($id, $city)


2 INSERT requests sind doch total verschwenderisch.. genauso wie 2 Datenbanken für diese daten die du speichern willst. Du machst es dir so nur komplizierter als es ist.

Barny
08.03.2019, 16:50
Er möchte nicht in eine Tabelle "inserten", sondern in 2 verschiedene. Und wenn der erste Insert erfolgreich war, der zweite aber nicht, dann soll ein komplettes Rollback passieren.

SQL-seitig kenne ich leider nichts. Wäre aber interessant zu wissen. Ich prüfe meine Daten vorher immer auf korrekte Syntax, Datentyp und teilweise auch Plausibilität bevor ich sie in die Tabellen schmeiße. Ggf. tue ich das auch nach meinem Insert und mache mein Rollback dann "manuell".

Viele Grüße,

Barny

gORDon_vdLg
08.03.2019, 17:44
Moin, ich glaube das Stichwort welches du suchst ist "transactions". Das ist quasi ein Mechanismus in SQL wo du mehrere Statements zusammenfügen kannst und diese erst mit einem abschließenden "commit" atomar durchgeführt werden.

shaq_
04.05.2019, 21:14
Danke an alle, vor allem an gordon.

Transactions ist genau das, was ich gesucht hatte.

Man kann z.B. in PHP mit


mysqli_autocommit($conn, FALSE)

das automatische Bestätigen von Änderungen der Datenbank aktivieren.

Dann führt man seine INSERTS und UPDATES wie gewohnt durch. Wenn dann an irgendeiner Stelle ein Fehler auftritt kann man diesen abfangen und mit


mysqli_rollback()

alles wieder auf den Zustand vor dem autocommit bringen.
Wenn alles ohne Probleme durchläuft setzt man die Änderungen mit
mysqli_commit($conn) um und schaltet autocommit wieder an.

gORDon_vdLg
08.05.2019, 17:32
Sehr gerne, schön dass es geklappt hat.