Mal wieder nur Probleme

Wie es halt immer so läuft, hat man mehr Probleme als Lösungen zur Hand. Ich hab da in einer MySQL Datenbank so eine Tabelle mit Benutzernamen und Passwörtern. Jetzt soll der Admin die Möglichkeit haben, Benutzer und Passwörter ändern zu können. Funktioniert auch bisher einigermaßen. Folgendes Problem tritt dabei auf: Stellen wir uns 2 Nutzer vor (A und B) und der Admin möchte deren Namen nun austauschen, dann kann er das tun im Webinterface, aber beim Commit streikt MySQL. Problem ist mein Unique-Constraint auf der Namensspalte. MySQL möchte den Constraint unbedingt nach jeder Aktion prüfen. Meine Daten sind aber nur zum Beginn der Transaktion konsistent und am Ende wieder, dazwischen aber nicht notwendiger Weise!

mysql> select PASSWORD_ID, username from password;
+-------------+-------------+
| PASSWORD_ID | username    |
+-------------+-------------+
|           3 | a           |
|           4 | b           |
|           2 | Musteradmin |
|           1 | Mustermann  |
+-------------+-------------+
4 rows in set (0.02 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.05 sec)

mysql> update password set username="b" where password_id=3;
ERROR 1062 (23000): Duplicate entry 'b' for key 2

Das Zauberwort heißt hier "deferred constraint resolution" und wird von MySQL leider nicht unterstützt! Dieses Feature würde die Constraints erst am Ende einer Transaktion prüfen.

Was mach ich nun aber mit meinem Webinterface? Eigentlich ist es ein Excel-mäßiges Grid, wo man alle Daten ändern kann und erst dann auf speichern klickt?

This entry was posted in coding, MySQL. Bookmark the permalink.

5 Responses to Mal wieder nur Probleme

  1. kunee says:

    Es ist zwar nicht besonders hübsch, aber in solchen Fällen nimmt man gerne Hilfswerte. Das du quasi drei Operationen machst statt zweien.

    3 a > 3 x
    4 b > 4 a
    3 x > 3 b

    ‘x’ muss dann irgendein Wert sein, der garantiert kein Benutzername sein kann.

    Wie bereits gesagt, nicht sehr hübsch, aber zumindest eine Lösung.

  2. kunee says:

    Eine weitere Lösung, wo ich gerade deinen letzten Satz lese.

    Da du ja anscheinend “alle” Datensätze in einem Grid darstellst, könntest du auch die komplette Table beim Submit neu schreiben. Dann werden alle Änderungen “übernommen”.

  3. Fabse says:

    Hallo kunee!

    das mit dem Hilfswert ist eine Variante, die ich nicht wirklich nutzen kann. Ich nutze Hibernate und da ändere ich bloß die reinen Java-Klassen und Hibernate macht den Rest. Außerdem kann man lange zirkuläre kreise bilden, wenn man lust hätte ;)

    und ob ein Truncate table; die lösung ist, geht doch auch um die userids! das macht nur noch mehr ärger.

    ich hab folgende 2 varianten überlegt:
    - dieses Tauschen erkennen und ablehnen = zwingt im zweifel den admin selbst zu einem temporären namen
    - oder die spalte nicht auf unique zu setzen sondern das per hand sicherstellen, dass am ende des tages (der transaktion) kein name doppelt ist = schwaches design :(

    bisher hab ich auch noch viel größere probleme mit anderen teilen der anwendung, so dass der admin hier bei derartigen versuchen nur einen stacktrace einer exception präsentiert bekommt, wenn er so einen mist versucht :)

  4. kunee says:

    Ja okay, mit einem O/R-Mapper gestaltet sich die Sache etwas schwieriger. Aber wieso packst du dein Passwort nicht mit in die User-Entity?

    USER
    – ID (PK)
    – USER_NAME
    – PASSWORD
    – …

    Okay, auch dann dürftest du den Benutzernamen nicht unique (auf Datenbankebene) machen. Schwieriger Fall. Aber wenn du an MySQL gebunden bist und die das nicht unterstützen, würde ich es so machen und auf Programmebene sicherstellen, dass der Benutzername eindeutig ist.

  5. Fabse says:

    kunee es freut mich, dass du mir bei meinen problemen helfen möchtest.

    natürlich speichere ich das passwort in der selben zeile, für mein beispiel hatte ich aber nur id und username ausgewählt…ich will ja nicht ablenken ;)

    die tabelle heißt natürlich immernoch “password” was etwas irritierend wirkt (ursprünglich gab es im system nur passwörter und keine name, aber das wollte jemand anders…)

    vielleicht guck ich mal, ob hibernate ja dieses deffered constraint checking kann? (denn die alternative wäre, dass es z.b. unter oracle über hibernate nicht nutzbar wäre)

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>