Ankündigung

Einklappen
Keine Ankündigung bisher.

insert ignore into & auto_increment

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • insert ignore into & auto_increment

    Hi,

    frage gibt es eine möglichkeit das auto_increment nur hochzählt wenn auch wirklich eine ID geschrieben wird?

    ich speichere in einer tabelle den versionsnamen von einem programm, sollte der name schon existieren wird auch nicht gespeichert. nur bekommt dann ein neuer name eine höhere id als nötig... bei mehreren zigtausend schreibvorgängen ist die id ruckzuck ganz groß.. (ok an BIGINT kommt sie nicht ran... aber dennoch)

    gibt es möglichkeiten?


    danke euch !!


  • #2
    Wieso sollte die ID erhöht werden wenn kein Eintrag vorgenommen wird?

    Kommentar


    • #3
      mhh macht er aber...

      wenn es einen eintrag gibt wird ignoriert.. aber hochzählen tuts trotzdem ??

      z.b. bei dieser tabelle (gibt noch mehr davon )

      PHP-Code:
      CREATE TABLE t_tet (
       
      f_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
       
      f_version varchar(100) DEFAULT NULL,
       
      PRIMARY KEY (f_id),
       
      UNIQUE `u_version`(`f_version`)
      ); 

      Kommentar


      • #4
        Zitat von taurus Beitrag anzeigen
        gibt es möglichkeiten?
        IGNORE nicht verwenden, und auf den ggf. aus der Verletzung des UNIQUE-Index resultierenden Fehler vernünftig abfangen.

        Kommentar


        • #5
          Es gibt wie immer mehrere Lösungsmöglichkeiten:

          a) Vermeiden, dass es überhaupt doppelte "Informationen" gemäß UNIQUE INDEX gibt.

          b1) Vorab die "doppelten" erkennen und aussortieren (siehe @ChrisB )
          b2) Die Daten im ersten Schritt in eine leere Temporäre Tabelle einlesen, dort die "doppelten" suchen/validieren/löschen. Anschließend den Rest in die "Echt-Tabellen" einlesen.

          c) Eine eigene laufende ID verwalten, die nicht automatisch durch den AUTO_INCREMENT erzeugt wird und diese beim INSERT beimischen. (ähnlich einer SEQUENCE, gibt es bei MySQL nicht)

          d) Bei "doppelten" einen UPDATE machen. Siehe auch REPLACE

          Code:
          REPLACE funktioniert auf exakt gleiche Weise wie INSERT. 
          Der Unterschied besteht darin, dass, wenn ein alter Datensatz
          denselben Wert wie ein neuer Datensatz für einen Primärschlüssel 
          oder einen eindeutigen Index hat, der alte Datensatz gelöscht
          wird, bevor der neue eingefügt wird.
          Grüße
          Thomas

          Kommentar


          • #6
            bei variante d sollte doch auch ein insert on duplicate key update funktionieren?
            1 feld1
            2 feld2

            und feld2 wird bei update und auto_increment nicht zu id3 ?? na dann variante d


            zu a) dazu müsste ich vorher ein select machen und prüfen obs das feld schon gibt.. (unnötiger zugriff. das muss doch auch anders gehen )

            zu b) ist ne möglichkeit, finde ich jetzt aber nicht so sauber..

            zu c) wär ne notlösung)

            Kommentar


            • #7
              Nein, ich glaube mein d) ist nicht die Lösung die Du suchst. Da MySQL einen DELETE plus neuen INSERT macht, wird auch wieder eine neue ID vergeben. d) Ist nur eine "relative einfache" Möglichkeit, insbesondere, wenn der "neue" Datensatz besser/wichtiger als der "alte" ist.

              Grüße
              Thomas

              Kommentar


              • #8
                mhh ja aber da kann ich ja dann auch gleich inser ignore lassen

                ich glaube ich werde chris lösung nehmen...
                ein einfaches insert und nur diesen einen fehler abfangen.. alle andere gehen dann mit ins error reporting mit rein...

                dank euch

                Kommentar


                • #9
                  mhh, ungünstig...
                  ich hab nun ein einfaches INSERT. wenn ein fehler auftritt mit "duplicate entry" wird die fehlermeldung ignoriert...

                  trotzdem... bei mehreren fehlgeschlagenen und anschließend einem erfolgreichen insert ist die id trotzdem höher als einträge vorhanden..


                  eine eigene id ist glaube ich keine sehr gute lösung (ich frage mehrere server ab.. und das wird dann verdammt unübersichtlich mit den ganzen schleifen und i's

                  was ich noch in betracht ziehe ist ein select.. wenn vorhanden dann kein insert... ist ja jetzt nicht sooo performancelastig.. (in der tabelle gibt es ja nur zwei einträge.. id und version(msg)

                  anbei was ich bisher habe.. (ist c++, aber keine angst ist einfach zu verstehen.. und macht ja im prinzip nicht mehr als den mysql_fehler nach dem query abzufangen..)
                  PHP-Code:
                  version_query "INSERT INTO t_pro (f_version) VALUES ('";
                                          
                  version_query += fin_out[6];
                                          
                  version_query += "')";
                                          
                  version_query_result mysql_query(connversion_query.c_str());

                                          if(
                  version_query_result != 0) {

                                              
                  std::string mysqlerr;
                                              
                  mysqlerr mysql_error(&mysql);

                                              if(
                  mysqlerr.find("Duplicate entry") != std::string::npos){
                                                  
                  IGNORE Duplicate Entry (because of auto_increment in INSERT IGNORE Statement..)
                                              } else {
                                                  
                  errormsg += "Error: Insert VERSION Query failed! >> Code: ";
                                                  
                  errormsg += mysql_error(&mysql);
                                                  
                  errormsg += " Vers.: ";
                                                  
                  errormsg += iout[6];
                                                  
                  errormsg += " -- ";
                                              } 

                  Kommentar


                  • #10
                    Für mich sind die Varianten b) die derzeit besten Lösungen, also entweder b2) eine Temporäre Zwischentabelle oder b1) Vor jedem INSERT ein SELECT im Sinne von.

                    Code:
                    b2) Schema:
                    
                    SELECT 1 AS schon_da FROM t_tet
                     WHERE f_version = 'xxxx';
                     
                    -> schnelles lesen da ein UNIQUE INDEX auf 'f_Version' existiert.
                    
                    
                    IF ($bSchon_da) {
                      // Meldung 'doppelter UNIQUE Key'
                    } else {
                     
                      -> INSERT ....
                    }
                    Vermutlich ist b2) die schnellere Methode, was zu testen wäre.

                    Grüße
                    Thomas

                    Kommentar


                    • #11
                      du meinst in deinem beispiel wohl "b1) schema"


                      wie darf ich mir varaiant b2 eine temporärere zwischentabelle vorstellen?

                      Kommentar


                      • #12
                        Methode b2 taugt nichts, weil nicht atomar.

                        Das müsste wenigstens in eine Transaktion gekapselt werden, damit es zuverlässig ist.

                        Kommentar


                        • #13
                          Methode b2 taugt nichts, weil nicht atomar.
                          was meinst du damit?

                          methode b2(mit temp tabelle) in eine transaktion oder b1 (select + insert)?
                          methode b2 nehm ich an... bei b1 gibts entweder einen datensatz oder nicht

                          Kommentar


                          • #14
                            Zitat von taurus Beitrag anzeigen
                            du meinst in deinem beispiel wohl "b1) schema"


                            wie darf ich mir varaiant b2 eine temporärere zwischentabelle vorstellen?
                            Genau, mein SELECT/INSERT Beispiel sollte natürlich b1) heißen, sorry.


                            Ein b2) Schema könnte so aussehen:

                            1) LOAD DATA oder per INSERT komplett und direkt in eine leere Tabelle t_tet_temp

                            2) Nur die "neuen" und geprüften Daten in die Echt_tabelle einlesen

                            INSERT INTO t_tet
                            SELECT * FROM t_tet_temp t
                            WHERE t.f_version NOT IN ( SELECT f_version FROM t_tet );

                            3) Leeren der t_tet_temp Tabelle mit DROP TABLE / CREATE TABLE oder eine echte "TEMPORARE TABLE" verwenden, die wird am Ende der Datenbankconnection automatisch entfernt.

                            Anstatt x-mal kleine Prüfungen, erfolgt hier die "Dupletten-Prüfung" auf einmal.

                            Grüße
                            Thomas

                            Kommentar


                            • #15
                              PHP-Code:
                              INSERT INTO t_tet
                              SELECT 
                              FROM t_tet_temp t
                              WHERE t
                              .f_version NOT IN SELECT f_version FROM t_tet ); 
                              sieht für mich genauso aufwendig aus wie ein selct und anschließend insert...

                              werde wohl die variante mit select und insert benutzen...

                              Kommentar

                              Lädt...
                              X