Regenbogenjonny: mysql: Doppelte Einträge verhindern

Hallo,

ich verhindere Doppeleinträge in einer meiner Tabellen über einen unique Index auf einer Spalte.

Beim Eintragen einer Zeile prüfe ich dann per do-while Schleife auf Fehler 1062 und zähle eben entsprechend lange hoch, bis der freie Eintrag gefunden wurde.

Jetzt habe ich eine andere Tabelle, bei der es bisher erlaubt war, in einer Spalte doppelte Einträge vorzunehmen, aber ab sofort möchte ich das ändern.

Wie kann ich vorhgehen? Ich kann, meine ich, auf die Spalte nur einen unique Index setzen, aber nicht sowas wie "unique Index ab ID 1000"?

Gibt es hierfür eine mysql-Lösung oder muß ich das in meiner Scriptsprache zur mysql- Verwendung lösen?

Jonny

  1. Tach!

    Wie kann ich vorhgehen? Ich kann, meine ich, auf die Spalte nur einen unique Index setzen, aber nicht sowas wie "unique Index ab ID 1000"?

    Ich kenne kein nennenswertes DBMS, das berechnete Indexe kennt (dBASE hatte das damals, aber heutzutage?). Dein Fall wäre aber auch noch eine Ecke komplexer und ein sehr spezieller Fall, so dass es dafür wohl kaum eine Lösung von der Stange geben wird.

    Gibt es hierfür eine mysql-Lösung oder muß ich das in meiner Scriptsprache zur mysql- Verwendung lösen?

    Auch MySQL hat eine Programmiersprache an Bord. In der Dokumentation unter Stored Procedure zu finden.

    dedlfix.

    1. Auch MySQL hat eine Programmiersprache an Bord. In der Dokumentation unter Stored Procedure zu finden.

      Hm... dann kann ich auch php nehmen. Gibt es eine "narrensichere" Methode als kurz vor dem Eintrag in der Tabelle nachzuschauen, ob es den Eintrag in der pseudo-unique-Spalte schon gibt? Oder soll ich für diesen kurzen Moment die Tabelle sperren? Was ist hier die sinnvollste Lösung?

      Jonny

      1. Tach!

        Auch MySQL hat eine Programmiersprache an Bord. In der Dokumentation unter Stored Procedure zu finden.

        Hm... dann kann ich auch php nehmen.

        Ja, aber dann musst du mehrere SQL-Statements formulieren, absenden, auf Fehler bei der Ausführung prüfen und das Ergebnis auswerten. Es ist übersichtlicher, das in einem System zu lösen, als ein System damit zu beauftragen, ein anderes zu bedienen.

        Gibt es eine "narrensichere" Methode als kurz vor dem Eintrag in der Tabelle nachzuschauen, ob es den Eintrag in der pseudo-unique-Spalte schon gibt?

        Besonders toll ist diese Lösung nicht, weil man damit ein TOCTTOU-Problem hat. Zwischen Abfrage und Eintragen können andere Prozesse dazwischenpfuschen.

        Oder soll ich für diesen kurzen Moment die Tabelle sperren?

        Transaktion fallen mir da auch noch ein. Aber hier kann ich dir nicht mit Erfahrung dienen, wie sich das verhält mit dem Verhindern paralleler Zugriffen. Da musst du mal das Handbuch befragen.

        Was ist hier die sinnvollste Lösung?

        Am besten ist immer noch ein Unique Index. Ich könnte mir noch als Lösung vorstellen, eine zweite Spalte für das neue System einzuführen. Ab jetzt bekommt das bisherige Feld NULL eingetragen und das neue Feld ein NULL für alle bisherigen Werte (machts von selbst, wenn du sie als NULL (also nicht NOT NULL) anlegst). Trotz Unique Index darf man ja beliebig viele NULL-Einträge haben. Beim Abfragen nimmst du COLAESCE(neu, alt) und bekommst immer den ersten Nicht-NULL-Wert, also entweder den einen oder den anderen Wert. - Die Sache hat nur einen Haken, sie kann nicht sicherstellen, dass es keine Dopplungen mit alten Werten gibt. Leider kannst du auch keinen auto_increment mit Startwert vergeben, weil das die NULL-Felder ausfüllen will.

        dedlfix.

    2. Ich kenne kein nennenswertes DBMS, das berechnete Indexe kennt (dBASE hatte das damals, aber heutzutage?). Dein Fall wäre aber auch noch eine Ecke komplexer und ein sehr spezieller Fall, so dass es dafür wohl kaum eine Lösung von der Stange geben wird.

      Oracle. Das Stichwort lautet: function based index

      1. Tach!

        Ich kenne kein nennenswertes DBMS, das berechnete Indexe kennt (dBASE hatte das damals, aber heutzutage?). Dein Fall wäre aber auch noch eine Ecke komplexer und ein sehr spezieller Fall, so dass es dafür wohl kaum eine Lösung von der Stange geben wird.

        Oracle. Das Stichwort lautet: function based index

        Ok, also Oracle kann function based indexes, aber bekommst du damit den zweiten Teil gelöst, einen Unique Index auf nur einen Teil der Datensätze zu legen?

        dedlfix.

        1. Ok, also Oracle kann function based indexes, aber bekommst du damit den zweiten Teil gelöst, einen Unique Index auf nur einen Teil der Datensätze zu legen?

          Dafür sorgen, dass diese Zeilen dort null bekommen. Sollte funktionieren. Ich hab aber keine Lust, das jetzt zu testen ;)

  2. Hallo,

    ich verhindere Doppeleinträge in einer meiner Tabellen über einen unique Index auf einer Spalte.

    Beim Eintragen einer Zeile prüfe ich dann per do-while Schleife auf Fehler 1062 und zähle eben entsprechend lange hoch, bis der freie Eintrag gefunden wurde.

    Du zählst eine Zahl hoch durch addieren von 1 und kassierst beim Einfügen dauernd Fehler?

    Warum lässt du dir nicht einfach die maximale Zahl ausgeben, addierst 1 und hast einen Treffer? Gut, wenn ein anderer schneller war, gibts einen Fehler. Aber dann addierst du nochmal 1.

    Jetzt habe ich eine andere Tabelle, bei der es bisher erlaubt war, in einer Spalte doppelte Einträge vorzunehmen, aber ab sofort möchte ich das ändern.

    Wie kann ich vorhgehen? Ich kann, meine ich, auf die Spalte nur einen unique Index setzen, aber nicht sowas wie "unique Index ab ID 1000"?

    Kannst du die Einträge um eine laufende Zahl ergänzen? Also aus 100, 100 und 100 wird 1-100, 2-100 und 3-100? Danach kannst du dann die Unique-Eigenschaft der Spalte setzen.

    Linuchs

    1. Hi,

      Warum lässt du dir nicht einfach die maximale Zahl ausgeben, addierst 1 und hast einen Treffer? Gut, wenn ein anderer schneller war, gibts einen Fehler. Aber dann addierst du nochmal 1.

      Naja. Aber zwischen Prüfung und Addition kann jedesmal ein anderer schneller sein (theoretisch) und damit drehte ich mich dann im Kreise ;)

      Jonny