Nick: mysql5 Sortierreihenfolge bei create table vorgeben?

Hi,

ich generiere 2 temporäre Tabellen und erhalte bei einem anschließenden JOIN einen illegalen collation-mix.

Woher nimmt mysql beim Tabellen generieren den Standart-Wert für die collation und wie gebe ich nun einer dieser beiden Tabellen eine collations-Vorgabe mit?

Ich habe es mit folghendem State versucht, aber so geht es wohl eher nicht:

CREATE TEMPORARY TABLE _table_1 SELECT FROM_UNIXTIME(Timestamp, '%Y%-%m') AS ym collate latin1_german1_ci, ...

Gruß, Nick

  1. Hi!

    ich generiere 2 temporäre Tabellen und erhalte bei einem anschließenden JOIN einen illegalen collation-mix.

    Woher nimmt mysql beim Tabellen generieren den Standart-Wert für die collation und wie gebe ich nun einer dieser beiden Tabellen eine collations-Vorgabe mit?

    Wenn du keinen angibst, dann wird für die Tabelle der Wert aus der Datenbank genommen. Letztlich interessiert jedoch nur der Wert des jeweiligen Feldes. Felder bekommen ohne explizite Angabe ihren Wert von der Tabelle.

    Ich habe es mit folghendem State versucht, aber so geht es wohl eher nicht:
    CREATE TEMPORARY TABLE _table_1 SELECT FROM_UNIXTIME(Timestamp, '%Y%-%m') AS ym collate latin1_german1_ci, ...

    Ist das eine Syntax, wie sie das Handbuch beschreibt? Warum probierst du mit einer der dort angegebenen Varianten?

    Dein Problem ist nicht die Charset/Collation-Angabe der Tabelle. Bei einem CREATE TABLE ... SELECT ... bekommen die neuen Felder die gleiche Kollation wie die übernommenen Felder. Bei berechneten Feldern, wie in deinem Fall, wird die Kodierung/Kollation der Verbindung verwendet, also die, die du mit mysql_set_charset() oder SET NAMES eingestellt hast. Wenn du explizit eine angeben möchtest, musst du das bei der Felddefinition (im CREATE-Teil) machen oder mit einem CONVERT(... USING ...) arbeiten.

    Lo!

    1. Dein Problem ist nicht die Charset/Collation-Angabe der Tabelle. Bei einem CREATE TABLE ... SELECT ... bekommen die neuen Felder die gleiche Kollation wie die übernommenen Felder. Bei berechneten Feldern, wie in deinem Fall, wird die Kodierung/Kollation der Verbindung verwendet, also die, die du mit mysql_set_charset() oder SET NAMES eingestellt hast. Wenn du explizit eine angeben möchtest, musst du das bei der Felddefinition (im CREATE-Teil) machen oder mit einem CONVERT(... USING ...) arbeiten.

      hi dedlfix,

      gut, die antwort bringt mich erstmal weiter.

      morgen versuch ich das umzusetzen und melde mich dann noch mal.

      wäre nett, wenn du den thread im auge behältst.

      viele grüße, nick

      1. Hi,

        mit dedlfix' Anregung bin ich weiter gekommen, aber ganz anders als gedacht und ich verstehe auch mysqls Verhalten nicht.

          
        mysql_query("SET NAMES 'latin1_german_ci'", $db);  
          
        $charset = mysql_client_encoding($db);  
        printf("MySQL Verbindungszeichensatz ist: %s\n<br />", $charset);  
        
        

        ergibt in der Ausgabe:

        MySQL Verbindungszeichensatz ist: latin1

        1267: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='

          
        mysql_query("SET NAMES 'utf8'", $db);  
          
        $charset = mysql_client_encoding($db);  
        printf("MySQL Verbindungszeichensatz ist: %s\n<br />", $charset);  
        
        

        ergibt in der Ausgabe:

        MySQL Verbindungszeichensatz ist: latin1

        und soinst keine weiter Fehlermeldung mehr!

        Kann mir dazu jemand den Hintergrund erklären?

        Grüße, Nick

        1. Hi!

          mysql_query("SET NAMES 'latin1_german_ci'", $db);

          SET NAMES will nur die Kodierungsinformation haben, also nur latin1. Die Anführungszeichen können entfallen. Die Kollation kann man mit der Klausel COLLATE angeben, also vollständig: SET NAMES latin1 COLLATE latin1_german_ci

          $charset = mysql_client_encoding($db);
          printf("MySQL Verbindungszeichensatz ist: %s\n<br />", $charset);
          ergibt in der Ausgabe:
          MySQL Verbindungszeichensatz ist: latin1

          1267: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='

          Das latin1_swedish_ci ist die Default-Einstellung. Das bedeutet, dass an irgendeiner Stelle keine explizite Angabe zur Kodierung/Kollation gemacht wurde. Dein Einfluss als Nicht-Admin erstreckt sich dabei auf deine Datenbank, die Tabellen darin und deren Felder sowie auf die Angaben zur Verbindung. Außerdem kommen noch selten benötigte individuelle Angaben wie bei CONVERT() oder String-Literalen hinzu.

          mysql_query("SET NAMES 'utf8'", $db);
          $charset = mysql_client_encoding($db);
          printf("MySQL Verbindungszeichensatz ist: %s\n<br />", $charset);
          ergibt in der Ausgabe:
          MySQL Verbindungszeichensatz ist: latin1

          Kein Wunder. mysql_client_encoding() befragt die Client-API. Ein SET NAMES geht aber an der Client-API vorbei und veranlasst nur den Server, sich umzustellen. mysql_client_encoding() kann dir als nicht den richtigen Wert liefern. Das kann es nur, wenn mysql_set_charset() für die Einstellung der Verbindungscodierung verwendet wurde. Diese Funktion redet mit der Client-API, die nun einerseits selbst Bescheid weiß und andererseits die Angabe an den Server übermittelt. Davon betroffen ist auch die Funktion mysql_real_escape_string(), die bei SET NAMES im Prinzip nicht richtig arbeiten kann. Allerdings hat das nur Auswirkungen auf einige asiatische Kodierungen, nicht jedoch auf latin1 und utf8.

          Damit sollte nun klar sein, dass die erste Ausgabe des latin1 zufällig gestimmt hat.

          und soinst keine weiter Fehlermeldung mehr!
          Kann mir dazu jemand den Hintergrund erklären?

          Erklärt hab ich es ja schon, nun solltest du die Stelle suchen, an der du vergessen hast, die Kodierung/Kollation selbst festzulegen.

          Das MySQL-Handbuch behandelt dieses Thema übrigens im Kapitel Character Set Support.

          Lo!

          1. Erklärt hab ich es ja schon, nun solltest du die Stelle suchen, an der du vergessen hast, die Kodierung/Kollation selbst festzulegen.

            Hi dedlfix,

            ich finde die Stelle nicht und Abhilfe schafft anscheinend nur, dass ich über set names die Verbindung auf utf-8 setze.

            Warum gerade DAS hilft, dazu hattest Du leider noch nichts gesagt.

            Hast Du ne Idee, warum gerade DAS hilft?

            Grüße, Nick

            1. Hi!

              Erklärt hab ich es ja schon, nun solltest du die Stelle suchen, an der du vergessen hast, die Kodierung/Kollation selbst festzulegen.
              ich finde die Stelle nicht und Abhilfe schafft anscheinend nur, dass ich über set names die Verbindung auf utf-8 setze.
              Warum gerade DAS hilft, dazu hattest Du leider noch nichts gesagt.

              Du darfst nicht davon ausgehen, dass alles per Default so eingestellt ist, wie du es brauchst. Du musst dich um jede Stelle selbst kümmern. Wichtig sind üblicherweise die Angaben zu den Feldern und die der aktuellen Verbindung (mysql_set_charset() - oder SET NAMES als Ersatz mit den genannten/gesehenen Nachteilen).

              Da du Probleme mit der Kollation hast, musst du auch diese beachten.

              SHOW VARIABLES LIKE 'collation%';

              Schau dir die Werte von den auf _client und _connection endenden Variablen an. Weiterhin ist für deine temporäre Tabelle die Kollationsangabe deiner geöffneten Datenbank von Interesse, wenn du keine Feldkollationen selbst festlegst.

              Wenn es da irgendwelche Differenzen gibt, beseitigst du diese am besten. Notfalls, indem du genannten Variablen für deine aktuelle Session umstellst. (mysql_set_charset() oder SET NAMES beeinflussen ja nur die Kodierung.)

              Lo!