SebastianJu: MySQL Select mit Umlauten fehlerhaft...

Hallo,

kann mir jemand mit diesem Phänomen weiterhelfen?

Ich habe eine MySQL-Datenbank Version: 5.0.41-community-nt

Darauf eine Datenbank mit collation: latin1_german1_ci

Alle Tabellenspalten und Tabellen haben auch diese collation.

Unter Anderem gibt es eine Tabelle mit den Feldern uid (int) und keyword (varchar 100). Darin werden nun Keywords gespeichert. Dabei ist mir aufgefallen dass manche Keywords nicht gespeichert werden. Beispielsweise die zwei Keywords:

cheats fur pc
cheats für pc

Das erste ist ein Typo der halt auch so gespeichert werden soll. Das Problem ist dass nur das erste Keywort gespeichert wird. Wenn beim zweiten Keywort angekommen ist dann wird ein select ausgeführt mit "where keyword = 'cheats für pc'". Dabei wird aber als Ergebnis der Datensatz von "cheats fur pc" zurückgeliefert. Das ist natürlich so nicht richtig.

Wie kann ich dass denn lösen?

Grüße!
Sebastian

  1. Hallo,

    Ich habe eine MySQL-Datenbank Version: 5.0.41-community-nt

    Bei mir 5.0.51-community-nt ...

    Darauf eine Datenbank mit collation: latin1_german1_ci
    Alle Tabellenspalten und Tabellen haben auch diese collation.
    Dabei ist mir aufgefallen dass manche Keywords nicht gespeichert werden. Beispielsweise die zwei Keywords:

    cheats fur pc
    cheats für pc

    Wenn beim zweiten Keywort angekommen ist dann wird ein select ausgeführt mit "where keyword = 'cheats für pc'". Dabei wird aber als Ergebnis der Datensatz von "cheats fur pc" zurückgeliefert. Das ist natürlich so nicht richtig.

    Dieses Verhalten kann ich nicht nachvollziehen. Ich kann problemlos beide Werte speichern und gezielt über eine Abfrage auslesen. Die WHERE-Klausel arbeitet erwartungsgemäß. Mit welchem Client setzt Du Deine Abfrage ab?

    Freundliche Grüße

    Vinzenz

    1. Ich benutze Xampp 1.6.2 portabel installiert. Verstehe ich nicht dass es bei dir klappt... Ich versuche das ganze jetzt mal komplett als SQL-Anweisungen dazustellen. Vielleicht bringt das was...

      Grüße!
      Sebastian

      1. Also, wenn ich die Tabellen lösche mit:

        delete FROM tab_keywords;

        und dann diese SQL-Anweisungen ausgeführt werden:

        SELECT * FROM tab_keywords as t1 where t1.keyword = 'Cheats fur PC'  
        insert into tab_keywords (keyword) values('Cheats fur PC')  
        uid=2302  
        SELECT * FROM tab_keywords as t1 where t1.keyword = 'Cheats für PC'  
        uid=2302
        

        dann wie man sieht passiert das was nicht passieren sollte...

        Wenn ich noch einmal lösche und direkt in phpmyadmin diese beiden zeilen ausführe dann erhalte ich ebenso den falschen Datensatz:

        insert into tab_keywords (keyword) values('Cheats fur PC')  
        SELECT * FROM tab_keywords as t1 where t1.keyword = 'Cheats für PC'
        

        Wie gesagt ist mir dieses Verhalten bisher nicht begegnet...

        Grüße!
        Sebastian

        1. Hallo,

          delete FROM tab_keywords;

          das CREATE-TABLE-Statement wäre interessant zu wissen. (SHOW CREATE TABLE tab_keywords)

          SELECT * FROM tab_keywords as t1 where t1.keyword = 'Cheats fur PC'

          insert into tab_keywords (keyword) values('Cheats fur PC')
          uid=2302

          versteh' ich nicht, gibt Syntaxfehler.

          SELECT * FROM tab_keywords as t1 where t1.keyword = 'Cheats für PC'
          uid=2302

            
          
          > dann wie man sieht passiert das was nicht passieren sollte...  
            
          ich sehe nichts davon.  
            
          Folgendes funktioniert bei mir reproduzierbar und völlig erwartungsgemäß mit der phpMyAdmin-Einstellung  
            
              Zeichensatz / Kollation der MySQL-Verbindung: latin1\_german1\_ci  
            
          Erstelle die Tabelle:  
            
          ~~~sql
            
          CREATE TABLE `tab_keywords` (  
          `uid` INT NOT NULL AUTO_INCREMENT ,  
          `keyword` VARCHAR( 100 ) CHARACTER SET latin1 COLLATE latin1_german1_ci NULL ,  
          PRIMARY KEY ( `uid` )  
          ) ENGINE = MYISAM CHARACTER SET latin1 COLLATE latin1_german1_ci
          

          Füge zwei Datensätze ein:

          INSERT INTO  
              tab_keywords (  
                  uid,  
                  keyword  
              )  
          VALUES  
              (NULL, 'Cheats fur PC'),  
              (NULL, 'Cheats für PC')  
          
          

          2 Zeile(n) eingefügt.
          ID der eingefügten Zeile: 2 ( die Abfrage dauerte 0.1220 sek. )

          Frage den Inhalt ab:

          SELECT  
              uid,  
              keyword  
          FROM  
              tab_keywords
          

          uid | keyword
          ----+-----------------
            1 | Cheats fur PC
            2 | Cheats für PC

          Selektiere spezielles Keyword:

          SELECT  
              uid,  
              keyword  
          FROM  
              tab_keywords  
          WHERE  
              keyword = 'Cheats fur PC'  
          
          

          uid | keyword
          ----+-----------------
            1 | Cheats fur PC

          Selektiere anderes spezielles Keyword:

          SELECT  
              uid,  
              keyword  
          FROM  
              tab_keywords  
          WHERE  
              keyword = 'Cheats für PC'  
          
          

          uid | keyword
          ----+-----------------
            2 | Cheats für PC

          Du machst irgendetwas falsch!

          Freundliche Grüße

          Vinzenz

          1. Ich habe jetzt folgenden Code ausgeführt:

            CREATE TABLE `tab_keywords2` (  
            `uid` INT NOT NULL AUTO_INCREMENT ,  
            `keyword` VARCHAR( 100 ) CHARACTER SET latin1 COLLATE latin1_german1_ci NULL ,  
            PRIMARY KEY ( `uid` )  
            ) ENGINE = MYISAM CHARACTER SET latin1 COLLATE latin1_german1_ci;  
              
            INSERT INTO  
                tab_keywords2 (  
                    uid,  
                    keyword  
                )  
            VALUES  
                (NULL, 'Cheats fur PC'),  
                (NULL, 'Cheats für PC');  
              
            SELECT  
                uid,  
                keyword  
            FROM  
                tab_keywords2;
            

            Ergebnis:

            1  	Cheats fur PC  
            2 	Cheats für PC
            

            Dann:

              
            SELECT  
                uid,  
                keyword  
            FROM  
                tab_keywords2  
            WHERE  
                keyword = 'Cheats fur PC';
            

            mit Ergebnis:

            1  	Cheats fur PC  
            2 	Cheats für PC
            

            und:

            SELECT  
                uid,  
                keyword  
            FROM  
                tab_keywords2  
            WHERE  
                keyword = 'Cheats für PC';
            

            mit Ergebnis:

            1  	Cheats fur PC  
            2 	Cheats für PC
            

            Er findet also immer alles...

            Woran könnte es denn sonst noch liegen? An irgendwelchen Datenbankeigenschaften? Auf der "home-Seite" gibt es einen Eintrag "Zeichensatz / Kollation der MySQL-Verbindung:" der steht auf utf8_unicode_ci. Ich habe den mal testweise auf german gesetzt aber das Ergebnis ist trotzdem nicht anders.

            Darüber steht noch "MySQL-Zeichensatz:  UTF-8 Unicode (utf8)" aber das kann ich offenbar nicht einstellen und auf Änderung testen.

            Grüße!
            Sebastian

  2. echo $begrüßung;

    Darauf eine Datenbank mit collation: latin1_german1_ci

    Die Kollation des einzelnen Feldes ist letzlich relevant, aber die sind ja bei dir gleich eingestellt.

    cheats fur pc
    cheats für pc

    Dass beides als gleich angesehen wird liegt an den Regeln der Kollation german1. Da ist eben definiert, dass sich bei Sortierungen uend Vergleichen ein ü wie ein u benimmt. Wenn du einen haargenauen Vergleich haben möchtest, nimm den BINARY-Operator dazu. Du kannst aber auch die Kollation auf *_bin umstellen, also latin1_bin in deinem Fall, dann wird auch zeichengenau verglichen.

    echo "$verabschiedung $name";

    1. Hm. Wieso funktioniert es dann bei Vinzenz?

      Jedenfalls habe ich jetzt mal:

      SELECT  
          uid,  
          binary keyword  
      FROM  
          tab_keywords2  
      WHERE  
          keyword = 'Cheats für PC'
      

      und

      SELECT  
          uid,  
          binary keyword  
      FROM  
          tab_keywords2  
      WHERE  
          binary keyword = 'Cheats für PC'
      

      probiert.

      Beim ersten wird geschrieben dass es ein Ergebnis gibt angeblich. "Zeige Datensätze 0 - 0 (1 insgesamt, die Abfrage dauerte 0.0011 sek.)". Aber angezeigt wird:

      1  	Cheats fur PC  
      2 	Cheats f�r PC
      

      Also beim zweiten Datensatz dieses falsche Zeichen.

      Und bei der zweiten Abfrage kommt kein Datensatz zurück.

      Grüße!
      Sebastian

      1. Ich habe mir deine verlinkte Seite noch mal durchgelesen und auch diese hier:

        http://dev.mysql.com/doc/refman/5.1/en/charset-collation-effect.html

        Nur erkenne ich immer noch keine Möglichkeit wie ich es hinbekomme dass a ae und ä auch als unterschiedlich angesehen werden...

        Grüße!
        Sebastian

      2. echo $begrüßung;

        Hm. Wieso funktioniert es dann bei Vinzenz?

        Ich weiß nicht, was Vinzenz (falsch) macht, bei mir verhält sich sein Beispiel so wie es soll: u wird wie ü behandelt. Ich bekomme immer beide Datensätze. Das ist für german1 so definiert, also verhält sich mein MySQL definitionsgemäß.

        Beim ersten wird geschrieben dass es ein Ergebnis gibt angeblich. "Zeige Datensätze 0 - 0 (1 insgesamt, die Abfrage dauerte 0.0011 sek.)". Aber angezeigt wird:

        Kann ich nicht nachvollziehen, bei mir läuft alles so wie es soll. Allerdings musste ich auf der Startseite vom phpMyAdmin die Kodierung der Verbindung auf Latin1 umstellen, sonst hat der PMA die Query UTF8-kodiert gesendet und ein UTF-8-ü ist logischerweise nicht binärkompatibel zu einem Latin1-ü.

        2 Cheats f�r PC
        Also beim zweiten Datensatz dieses falsche Zeichen.

        Bei mir nicht. Sieht aber danach aus, als ob jemand UTF-8 erwartet und Latin1 geschickt bekommt. Du hast irgendwo anders noch was nicht richtig gemacht. Vielleicht hantierst du mit einem PHP-Script, bei dem du vergessen hast, die gewünschte Kodierung nach dem Verbindungsaufbau auszuhandeln.

        echo "$verabschiedung $name";

  3. Ich glaube ich habe jetzt die Lösung. Statt varchar(100) benutze ich jetzt varbinary(100). Und nun kann ich in dieses uniquefeld die drei Versionen einbauen ohne Fehlermeldung:
    'cheats fur pc'
    'cheats für pc'
    'cheats fuer pc'

    Außerdem kann ich nun selects auf alle drei Versionen fahren und es werden jeweils immer die richtigen erkannt.

    Grüße!
    Sebastian