DBGrid und UNIQUE-Spalten



  • Hallo zusammen,

    ich benutzen dbExpress-Komponenten um in einer CLX-Anwendung auf eine Datenbank zuzugreifen.
    Genauer gesagt haben ich folgende Anbindung:

    TSQLConnection -> TSQLDataSet -> TDataSetProvider -> TClientDataSet -> TDataSource -> TDBGrid

    Ich greife damit auf eine Tabelle zu, die einen String, der eine Fremdsprache Bezeichnet und eine zugehörige ID speichert. Sie hat folgende Struktur:

    (Nummer int not null unique, Bezeichnung varchar(20))

    Der Inhalt der Tabelle sieht z.B. so aus:

    1 Spanisch
    2 Russisch
    3 Italienisch
    4 Französisch
    5 Türkisch
    6 Englisch

    Nun trage ich im DBGrid nacheinannder z.B. folgende Änderungen ein:

    Nummer von Russisch auf 7 setzen.
    Nummer von Italienisch auf 2 setzen.
    Nummer von Russisch auf 3 setzen.

    Obwohl die UNIQUE-Eigenschaft zu keinem Zeitpunkt verletzt wurde, erhalte ich beim Versuch die Änderungen die Datenbank zu schreiben zwei mal hintereinander jeweils einen EDatabaseError 'violation of PRIMARY or UNIQUE KEY Constraint "INTEG_3" on table "FREMDSPRACHEN".'
    und eine weitere Exception-Benachrichtigung auf deutsch 'Datensatz nicht gefunden; es wurde kein Schlüssel angegeben.'

    Mache ich einen Fehler oder ist es generell unzulässig UNIQUE-Werte auf diese Weise zu ändern? Falls ja, hat jemand eine Idee, wie man den Benutzer davon abhält derartige unzulässige Operationen durchzuführen, ohne die Änderung der ID komplett zu verbieten?

    Gruß
    Marc



  • Eine Lösung kann ich Dir nicht anbieten. Kann auch an der DB, respektive der Definition von ForeinKeys liegen, die das verhindert...

    Aber es sollte niemals eine Situation entstehen, in der eine UniqueID geändert werden muß. Schließlich muss in diesem Zug dann auch in allen Tabellen die ID geändert werden - eine nicht ganz trivilale Angelegenheit. Um diesen Aufwand nicht betreiben zu müssen, verwendet man ja die IDs. Zum einen mindert dies die Datenredundanz und zum anderen sind Änderungen an Bezeichnungen an nur einer einzigen Tabelle durchzuführen.
    Ein User sollte die ID eigentlich auch nicht modifizieren können. Die ID wird im Regelfall vom DB-System vorgegeben und dem User höchsten zur schnelleren Auswahl angeboten. 90% der UniqueIDs in meinen Datenbanken bekommt der User nie zu Gesicht.



  • Ich stimme Joe zu:
    Es liegt an dem Primary Key, den Du gesetzt hast. ⚠
    Ich gehe davon aus, dass Du das "Nummer"-Feld nicht nur als primary/unique Key gewählt hast, sondern ebenfalls ein auto-Inkrementier-Feld daraus gemacht hast, womit Dein DBMS sich die ID selber vergibt und Du Somit die Finger davon zu lassen hat. Denn sobald es ein auto-ink-Feld ist, ist der Zugriff auf diesen Wert nur über den damit verbundenen Generator zulässig. Wenn Du also unbedingt die IDs ändern willst, müsstest Du folgendermassen vorgehen:
    1. Dir (über eine evtl. angelegte stored_procedure) den aktuellen GenaratorWert holen (im BsP: 7).
    2. Diesen Generatorwert als neue ID nehemn und die Daten des zu verschiebenden Datensatzes dahinter schieben und speichern (im Bsp: "7 Russisch").
    3. Alle, ich wiederhole ALLE Foreign Keys, die auf den nun zu löschenden Datensatz (2) verweisen, zu ändern auf den neuen ( 7) --->(was weiss ich wo in deiner Bsp-DB foreign keys sind..... ;))
    4. Nun den alten (bereits kopierten und foreignkey freien DS löschen (im BsP den 2ten)
    5. Jetzt kannste den DS "3 Italienisch" nach "2 Italienisch" rüberkopieren
    6. Jetzt wie unter 3. bereits geschrieben dich um alle foreign keys von "3 Italienisch" kümmern.
    7. jetzt den DS "3 Italienisch" löschen
    8. Nun den DS "7 Russisch" nach "3 Russisch" kopieren
    9. Wierder einmal alle foreign keys von "7 Russisch" nach "3 Russisch" ändern
    10. den DS "7 Russisch" löschen
    11. den Generatorwert wieder auf 7 setzen.

    Es ist allerdings dringend davon abzuraten, dies zu tun, da nur Probs auftauchen, wenn man an den Generatoren und Keys rumspielt.

    Ist es den o.a. Aufwand wert?? 😮

    Gruß, Mouse


Anmelden zum Antworten