M.: Fehlermeldung bei vorhandenen Index in Mysql

Mahlzeit,

ich hab einen Index über mehrere Felder um doppelte Einträge zu verhindern und die Abfrage zu beschleunigen.
Aktuell wird die id (Auto-Incremtent) um eins erhöht und keine Fehlermeldung erzeugt.

Kann ich Mysql erklären, dass der Datensatz nicht geschrieben wird, der alte Eintrag erhalten bleibt und ich ne Fehlermeldung bekomme?

Alternativ müsste ich halt vorher noch abfragen, ob der Eintrag schon existiert, aber ich denke, ein Query ist performanter als zwei ;)

thx4hlp

--
eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
  1. Moin!

    ich hab einen Index über mehrere Felder um doppelte Einträge zu verhindern und die Abfrage zu beschleunigen.

    Unique?

    Was trägts Du ein?

      
    CREATE TABLE ab (  
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,  
    pid INT UNSIGNED NOT NULL DEFAULT 0,  
    aid INT UNSIGNED NOT NULL DEFAULT 0,  
    PRIMARY KEY (id),  
    UNIQUE KEY (pid, aid)  
    );
    

    insert into ab values('',2,3);

    #-> Query OK, 1 row affected, 1 warning (0.05 sec)

    insert into ab values('',2,3);
    #-> ERROR 1062 (23000): Duplicate entry '2-3' for key 'pid'

    geht doch ...

    1. Mahlzeit,

      insert into ab values('',2,3);
      #-> ERROR 1062 (23000): Duplicate entry '2-3' for key 'pid'

      geht doch ...

      Kann es sein, dass es daran liegt, dass der AI-Wert Unique ist und der Index über 4 Spalten Primary?

      Die Struktur hab ich als Antwort auf dedlfix gepostet

      --
      eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
      1. Die Struktur hab ich als Antwort auf dedlfix gepostet

        Ich glaube, Du hast genau da:

        PRIMARY KEY (`date`,`text`,`invoiceNr`,`accountNr`),  
        UNIQUE KEY `id` (`id`)
        

        PRIMARY und UNIQUE schlicht vertauscht.

        PRIMARY KEY `id` (`id`)  
        UNIQUE KEY (`date`,`text`,`invoiceNr`,`accountNr`),  
        
        

        Dann geht es auch so, wie Du es willst.

        Jörg Reinholz

        1. Mahlzeit,

          Dann geht es auch so, wie Du es willst.

          Es geht auch so, wie erwähnt lags am REPLACE statt INSERT
          Aber die Indizies passe ich trotzdem an. Hab die mit Chive angelegt und da wurde mir die Reihenfolge vorgegeben, weil beim auto_increment automatisch ein UNIQUE auf die id gesetzt wird.

          --
          eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
  2. Tach!

    ich hab einen Index über mehrere Felder um doppelte Einträge zu verhindern und die Abfrage zu beschleunigen.
    Aktuell wird die id (Auto-Incremtent) um eins erhöht und keine Fehlermeldung erzeugt.

    Rate ich richtig, dass dieser Index zum einen ein Unique Index ist (oder der Primary Key) und zum anderen ein Feld davon das Auto-Increment-Feld ist?

    Kann ich Mysql erklären, dass der Datensatz nicht geschrieben wird, der alte Eintrag erhalten bleibt und ich ne Fehlermeldung bekomme?

    In welchem Fall? Wenn du die Werte händisch vergibst? Auto-Increment vergibt nur dann einen Wert selbständig, wenn du keinen vorgibst oder 0 oder NULL (bei NOT-NULL-Feldern). Oder willst du dass der AI-Wert immer unterschiedlich ist, auch wenn durch unterschiedliche Werte im zweiten Feld bereits die Eindeutigkeit gegeben ist?

    Alternativ müsste ich halt vorher noch abfragen, ob der Eintrag schon existiert, aber ich denke, ein Query ist performanter als zwei ;)

    Erst prüfen und später schreiben ergibt auch ein TOCTTOU-Problem.

    dedlfix.

    1. Mahlzeit,

      erstmal danke, auch an Jörg.

      Rate ich richtig, dass dieser Index zum einen ein Unique Index ist (oder der Primary Key) und zum anderen ein Feld davon das Auto-Increment-Feld ist?

      Hätte die Struktur posten sollen, sorry.
      Die is ist Unique, Auto-Increment. Der zweite Index läuft über 4 Felder, deren Kombination nur genau einmal auftreten darf.

      Hier mal der CREATE:

      CREATE TABLE IF NOT EXISTS `xms_cashBook` (  
        `id` int(11) NOT NULL AUTO_INCREMENT,  
        `date` date NOT NULL,  
        `booked` date NOT NULL,  
        `text` varchar(255) NOT NULL,  
        `invoiceNr` varchar(255) NOT NULL,  
        `accountText` varchar(255) NOT NULL,  
        `accountNr` varchar(255) NOT NULL,  
        `taxRate` decimal(10,5) NOT NULL,  
        `purchaseExclTax` decimal(20,10) NOT NULL,  
        `description` text NOT NULL,  
        PRIMARY KEY (`date`,`text`,`invoiceNr`,`accountNr`),  
        UNIQUE KEY `id` (`id`)  
      ) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;
      

      In welchem Fall? Wenn du die Werte händisch vergibst? Auto-Increment vergibt nur dann einen Wert selbständig, wenn du keinen vorgibst oder 0 oder NULL (bei NOT-NULL-Feldern).

      Der wird nie per Hand vergeben.

      Oder willst du dass der AI-Wert immer unterschiedlich ist, auch wenn durch unterschiedliche Werte im zweiten Feld bereits die Eindeutigkeit gegeben ist?

      Ich will, dass erst gar nichts geändert wird in der Tabelle, wenn der Eintrag in der Kombination schon existiert.

      Erst prüfen und später schreiben ergibt auch ein TOCTTOU-Problem.

      Ist ne Single-User Applikation, deshalb kann ich das Risiko abschätzen ;)
      Aber natürlich auch ein Aspekt der berücksichtigt werden muss.

      --
      eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
      1. Tach!

        Die is ist Unique, Auto-Increment. Der zweite Index läuft über 4 Felder, deren Kombination nur genau einmal auftreten darf.

        Ich hätte ja der ID den Primärschlüssel mit Auto-Increment ergeben und die anderen vier Felder in eine Unique-Index gesteckt. Welchen Gründ siehst du denn, das andersrum zu machen?

        PRIMARY KEY (date,text,invoiceNr,accountNr),
          UNIQUE KEY id (id)

        Ich will, dass erst gar nichts geändert wird in der Tabelle, wenn der Eintrag in der Kombination schon existiert.

        Wenn du bei einem INSERT die id oder dieselbe Kombination von date,text,invoiceNr,accountNr ein weiteres Mal einzugeben versuchst, gibt es eine Unique-Constraint-Verletzung und das Insert findet nicht statt. Außer du machst was mit ON DUPLICATE KEY UPDATE.

        Erst prüfen und später schreiben ergibt auch ein TOCTTOU-Problem.
        Ist ne Single-User Applikation, deshalb kann ich das Risiko abschätzen ;)
        Aber natürlich auch ein Aspekt der berücksichtigt werden muss.

        Ich will's ja nur mal gesagt haben, nicht dass noch jemand auf die Idee kommt, das wäre ein guter Lösungsweg.

        dedlfix.

        1. Mahlzeit,

          Ich hätte ja der ID den Primärschlüssel mit Auto-Increment ergeben und die anderen vier Felder in eine Unique-Index gesteckt. Welchen Gründ siehst du denn, das andersrum zu machen?

          Naja, Chive wollte es mich nicht anders machen lassen und beim Wissen über Mysql ist noch lückenhaft ;)
          Mal sehen ob es klappt, wenn ich das vertausche.

          Wenn du bei einem INSERT die id oder dieselbe Kombination von date,text,invoiceNr,accountNr ein weiteres Mal einzugeben versuchst, gibt es eine Unique-Constraint-Verletzung und das Insert findet nicht statt. Außer du machst was mit ON DUPLICATE KEY UPDATE.

          Die id wird nicht übergeben, es gibt ein Select, der die id erhöht (per auto_increment). Und anstatt einer Fehlermeldung bekomme ich eine Erfolgsmeldung.

          Ich will's ja nur mal gesagt haben, nicht dass noch jemand auf die Idee kommt, das wäre ein guter Lösungsweg.

          Ja, der Tip war gut, muss ich ja auf jedem Fall im Hinterkopf behalten, weiss ja nicht, was aus der Software irgendwann mal wird.

          PS: Ich glaub ich hab das Problem gefunden.
          Meine Mysql-Klasse schiesst einen Insert immer mit "REPLACE INTO" raus. Vermutlich liegt es daran. Ich werd das mal ändern und testen.

          --
          eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
          1. Mahlzeit,

            PS: Ich glaub ich hab das Problem gefunden.
            Meine Mysql-Klasse schiesst einen Insert immer mit "REPLACE INTO" raus. Vermutlich liegt es daran. Ich werd das mal ändern und testen.

            Das war der Fehler. Ein "INSERT INTO" wirft jetzt nen Duplicate entry
            Danke für die Hilfe von dir und von Jörg.
            Ich hab auf jedem Fall was gelernt. :)

            --
            eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...
          2. Tach!

            Ich hätte ja der ID den Primärschlüssel mit Auto-Increment ergeben und die anderen vier Felder in eine Unique-Index gesteckt. Welchen Grund siehst du denn, das andersrum zu machen?
            Naja, Chive wollte es mich nicht anders machen lassen und beim Wissen über Mysql ist noch lückenhaft ;)
            Mal sehen ob es klappt, wenn ich das vertausche.

            Ja, dreh das mal. Du kannst theoretisch die ID auch weglassen, denn die Eindeutigkeit ist bereits durch die anderen vier Werte gewährleistet. Sie dennoch zu behalten hat vorwiegend praktische Gründe, wenn man sie als Verweiswert braucht oder zum einfacheren Ansprechen des Datensatzes (eine Zahl statt 4 andere Werte).

            Die id wird nicht übergeben, es gibt ein Select, der die id erhöht (per auto_increment).

            Ein SELECT macht gar nichts mit den Werten.

            PS: Ich glaub ich hab das Problem gefunden.
            Meine Mysql-Klasse schiesst einen Insert immer mit "REPLACE INTO" raus. Vermutlich liegt es daran. Ich werd das mal ändern und testen.

            Ja, REPLACE löscht erst, wenn etwas existiert, und fügt dann ein. Da kann es keine doppelten Datensätze geben.

            dedlfix.

            1. Mahlzeit,

              Ja, dreh das mal. Du kannst theoretisch die ID auch weglassen, denn die Eindeutigkeit ist bereits durch die anderen vier Werte gewährleistet. Sie dennoch zu behalten hat vorwiegend praktische Gründe, wenn man sie als Verweiswert braucht oder zum einfacheren Ansprechen des Datensatzes (eine Zahl statt 4 andere Werte).

              Die id wird per get oder post übergeben damit ein Eintrag einfach aufgerufen werden kann. Der einzige Grund, wieso die existiert ;)

              Die id wird nicht übergeben, es gibt ein Select, der die id erhöht (per auto_increment).

              Ein SELECT macht gar nichts mit den Werten.

              Schreibfehler, natürlich ist es ein INSERT, wobei es in meinem Fall ein REPLACE war.

              Ja, REPLACE löscht erst, wenn etwas existiert, und fügt dann ein. Da kann es keine doppelten Datensätze geben.

              Genau. Und damit hab ich mir mein Problem hausgemacht.

              --
              eigentlich ist mir bewusst, dass ich hin und wieder einfach mal die Klappe halten sollte. Doch genau in den unpassendsten Momenten erwische ich mich dabei, wie ich dennoch etwas sage ...